Calculating the Bearing from One Point to Another

Sometimes it is helpful to know the bearing (i.e. the direction) of a path between two points. Here's two functions to help you calculate the bearing between two points, for the geometry datatype and the geography datatype respectively.

Geometry

The Bearing of the path between two points of the geometry datatype is a case of simple trigonometry:
CREATE FUNCTION dbo.GeometryBearing (
  @Point1 geometry,
  @Point2 geometry  )
RETURNS FLOAT
AS
BEGIN
  DECLARE @Bearing DECIMAL(18,15)
  DECLARE @dx FLOAT = @Point2.STX - @Point1.STX
  DECLARE @dy FLOAT = @Point2.STY - @Point1.STY
  IF (@Point1.STEquals(@Point2) = 1)
    SET @Bearing = NULL
  ELSE
    SET @Bearing = ATN2(@dx,@dy)
    SET @Bearing = (DEGREES(@Bearing) + 360) % 360
  RETURN @Bearing
END
GO
You can test out this function by checking one of the angles of a simple right-angled triangle with angles 30-60-90, as follows:
DECLARE @Point1 geometry = geometry::Point(0,0,0)
DECLARE @Point2 geometry = geometry::Point(1,SQRT(3),0)
SELECT dbo.GeometryBearing(@Point1, @Point2)

Geography

The Bearing of the path between two points of the geography datatype is a bit more complicated:
CREATE FUNCTION dbo.GeographyBearing (
  @Point1 geography,
  @Point2 geography  )
RETURNS FLOAT
AS
BEGIN
  DECLARE @Bearing DECIMAL(18,15)
  DECLARE @Lat1 FLOAT = RADIANS(@Point1.Lat)
  DECLARE @Lat2 FLOAT = RADIANS(@Point2.Lat)
  DECLARE @dLon FLOAT = RADIANS(@Point2.Long - @Point1.Long)
  IF (@Point1.STEquals(@Point2) = 1)
    SET @Bearing = NULL
  ELSE
    SET @Bearing = ATN2(
      SIN(@dLon)*COS(@Lat2),
     (COS(@Lat1)*SIN(@Lat2)) - (SIN(@Lat1)*COS(@Lat2)*COS(@dLon))
    )
    SET @Bearing = (DEGREES(@Bearing) + 360) % 360
  RETURN @Bearing
END
GO
Note that this is a simplistic determination of the bearing, based on a perfectly spherical model of the earth - it does not take into consideration the actual ellipsoidal model specified by the SRID of the geography instances supplied. You can then use this function to calculate the angle (0' being N) at which you'd initially have to set off from Vienna in order to take the shortest path to Moscow, as follows:
DECLARE @Vienna geography = geography::Point(16.37, 48.21, 4326)
DECLARE @Moscow geography = geography::Point(37.60, 55.75, 4326)
SELECT dbo.GeographyBearing(@Vienna,@Moscow)

Comments

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options