# Calculate weighted azimuth/bearing of a line

Given the line

``````LINESTRING(-9.086532643219698 -7.939337106873815,-1.396102955719698 -0.9775148048290135,-0.780868580719698 -0.7138718839794582,-0.077743580719698 -0.6699297767574899,0.581436106780302 -0.6699297767574899,1.372451731780302 -0.6699297767574899,1.987686106780302 -0.6699297767574899,2.690811106780302 -0.7578135712925369,3.218154856780302 -0.6699297767574899,0.801162669280302 1.1756755719445946,10.293350169280302 9.525132229415934)
``````

Which look likes this (start point is bottom left):

What is the correct methodology to find the overall azimuth which based on visual inspection should be something like this red line:

At first glance I figured if I calculate the azimuth between every point pair and then average them it would get what I want (something like https://social.msdn.microsoft.com/Forums/officeocs/en-US/74cd7844-30fe-43d3-a45e-9733c83d09b3/vector-average-function-in-tsql?forum=transactsql )

Using this approach the average azimuth is ~72.22 when I would expect it to be around ~50 degrees.

I realized that it doesn't take into consideration the length (magnitude) of each line segment, and the 2 dominant segments (both ~45 degree azimuth) only accounts for 2/10 of the average (2 point pairs of the total 10 point pairs).

So it seems liked I need to use the length of each segment as a weight to the average.

That's when I thought maybe vector math (dot product) is whats needed because I have a magnitude (length) and angle (azimuth); However, because the segments (vectors) are already lined up head to tail, the resultant vector's angle would just be the angle between the start point and end point (which is not what I am after)

I am looking for approaches to mathematically solve this problem, or references to what it's called that I am after.

• Why isn't the average direction for the track equal to the direction from the first to the last point? The wiggle in the middle should cancel itself out. Imagine a semicircle - what's the average direction of that? Its the diameter across the semicircle. For any arc, the average direction is the direction of the chord from start to finish. Jul 31, 2019 at 7:56
• Calculating bearing across a large area in units of degrees requires the use of geodetic functions, to properly handle the curvature of the spheroid, since the back angle isn't .equivalent to the angle that got there. The name of this task is the second Geodetic Problem (aka Inverse aka Reverse). There are a multitude of libraries to solve this. Jul 31, 2019 at 9:34
• @Spacedman I agree that's true for an arc, but I am not sure about a piece-wise line segment. Consider this line segment i.vgy.me/HpNkVS.png Is the overall azimuth 90 degrees? It doesn't seem like it because I agree that the the y-components cancel each other out the x-components do not; You could be right though. When I think of an object starting at one point and maintain a constant speed, what bearing will that object spend most of its time? To me it would be the long part pointing ~135 Aug 1, 2019 at 5:06
• @Vince I am not concerned with large area in units, I used such large corrdinates in the example because it was easy to make the Well Known Text easily with arthur-e.github.io/Wicket/sandbox-gmaps3.html - An approximation is suitable for my needs, just looking for methodologies and less reference to libraries (because I want to implement a SQL solution) Aug 1, 2019 at 5:06
• @CuriousDeveloper yes the mean direction for that path is heading East. Sure it spent a lot of time going in SE direction but then it turned round and went due N to get back on track. I'm pretty sure that will integrate out to an overall Easterly average. Aug 1, 2019 at 6:17

I never followed up on if this was the best approach, but I have a feeling it is. TSQL Function:

``````-- Create date: 6/24/2019
-- Description: Calculate the bearing of a line
--              10/29/2019: Modified to use formula at https://web.archive.org/web/20190418070658/http://instantglobe.com/CRANES/GeoCoordTool.html to be geodetic
-- =============================================
CREATE FUNCTION [dbo].[fnLineBearing]
(
@LineString geometry
)
RETURNS FLOAT
AS
BEGIN
DECLARE @StartPoint GEOMETRY = @LineString.STStartPoint();
DECLARE @EndPoint GEOMETRY = @LineString.STEndPoint();

DECLARE @lat1 FLOAT;
DECLARE @lat2 FLOAT;
DECLARE @dLon FLOAT;

DECLARE @y DECIMAL(18, 15) = SIN(@dLon) * COS(@lat2);
DECLARE @x DECIMAL(18, 15) = COS(@lat1) * SIN(@lat2) -
SIN(@lat1) * COS(@lat2) * COS(@dLon);

DECLARE @d FLOAT  = ATN2(@y, @x)

SET @d = @d * CAST(180.0 AS FLOAT) / PI();

-- Normalize bearing ...
RETURN
CASE
WHEN @d < 0.0
THEN @d + CAST(360.0 AS FLOAT)
WHEN @d >= 360.0
THEN @d - CAST(360.0 AS FLOAT)
ELSE @d
END;
END
``````