I recently needed to find the average of two angles. I was programmatically creating a irregular polygon. I wanted to draw a small square at the points of the polygon, and I wanted the squares to be rotated to the average of the two lines that met at that point.
The issue is that if you have two bearings, one at 20° and one at 350°, or one at 15° and one at 315°. If you just average the two numbers, you get 185°, but the more appropriate number is 5°. This is called by some a “Wraparound issue” and if you search the web you will see lots of ways to solve this problem. Unfortunately they mostly try to solve it using a mathematical equation. Now for people that have read this blog for awhile know that I am not allergic to math, but if we can solve this problem simply with an algorithm, we should … that’s what computers are for, right?
So, here is my algorithm and the thought behind it.
(Assumptions: 0 >= bearings < 360)
First if you look at the difference between the two bearings, you will see that there are two possibilities, the actual difference is greater than 180° or less than 180°. Since we are only concerned about “fixing” the issue when the difference is greater than 180°, that is the first thing we will check.
We will call the smaller value bearing bearingA and the larger value bearing bearingB.
Since we know that bearingB has a larger value and that the difference is greater than 180, so bearingB > 180.
So, if we subtract 360 – bearingB, then just add bearingA + bearingB and divide the total in half, we are 90% there.
One last check. If the result is less than 0, we need to add 360 back in.
So, example #1 20° & 350° | So, example #2 15° & 315° |
And here is the code:
- private static double GetAverageBearing(double bearingA, double bearingB)
- {
- if (bearingA > bearingB)
- {
- var temp = bearingA;
- bearingA = bearingB;
- bearingB = temp;
- }
- if (bearingB - bearingA > 180) bearingB -= 360;
- var finalBearing = (bearingB + bearingA)/2;
- if (finalBearing < 0) finalBearing += 360;
- return finalBearing;
- }
1 comment:
Thanks! I believe there is a typo above in the example: 354 degrees should be 345 degrees.
I used this example to translate a VB equivalent. Here it is if anyone else is interested:
Public Function AverageBearing(ByVal BearingA As Double, ByVal BearingB As Double) As Double
Dim TempBearing As Double
Dim FinalBearing As Double
If BearingA > BearingB Then
TempBearing = BearingA
BearingA = BearingB
BearingB = TempBearing
End If
If (BearingB - BearingA) > 180 Then BearingB = BearingB - 360
FinalBearing = (BearingB + BearingA) / 2
If FinalBearing < 0 Then FinalBearing = FinalBearing + 360
AverageBearing = FinalBearing
End Function
Post a Comment