ProjNet4GeoAPI icon indicating copy to clipboard operation
ProjNet4GeoAPI copied to clipboard

Bearing and Reverse bearing

Open eiredrake opened this issue 7 years ago • 3 comments

Is there a way to to calculate bearing and reverse bearing between points?

thanks!

eiredrake avatar Nov 26 '18 14:11 eiredrake

I don't think so. If so, it wouldn't really be anything that ProjNet4GeoAPI adds, since this library is just concerned with coordinate transformations.

You could, for example, use a conformal projection and compute angles there using NetTopologySuite, but that wouldn't really be different than just computing the angles on the unprojected coordinates.

Mike Gavaghan wrote a Geodesy library in both Java and C#... I copied the C# one onto GitHub (with his permission) at airbreather/Gavaghan.Geodesy, which seems a bit more promising.

GeodeticCalculator.CalculateGeodeticCurve can give you a GeodeticCurve which has the Azimuth / ReverseAzimuth, which you should be able to translate to bearing / reverse bearing, right?

airbreather avatar Nov 27 '18 13:11 airbreather

Rolled back around to this and had a hard time remembering where I'd asked the question. but thank you I'll look into it. I appreciate the referral.

eiredrake avatar Feb 26 '19 19:02 eiredrake

Something like this?

/// <summary>
		/// 
		/// </summary>
		public enum CompassDirection
        {
			N,
			NE,
			E,
			SE,
			S,
			SW,
			W,
			NW
        }

		/// <summary>
		/// 
		/// </summary>
		/// <param name="bearing"></param>
		/// <returns></returns>
		[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
		public static CompassDirection GetCompassDirection(double bearing)
        {
			if (bearing >= 0 && bearing <= 22.5)
			{
				return CompassDirection.N;
			}
			else if (bearing >= 22.5 && bearing <= 67.5)
			{
				return CompassDirection.NE;
			}
			else if (bearing >= 67.5 && bearing <= 112.5)
			{
				return CompassDirection.E;
			}
			else if (bearing >= 112.5 && bearing <= 157.5)
			{
				return CompassDirection.SE;
			}
			else if (bearing >= 157.5 && bearing <= 205.5)
			{
				return CompassDirection.S;
			}
			else if (bearing >= 202.5 && bearing <= 247.5)
			{
				return CompassDirection.SW;
			}
			else if (bearing >= 247.5 && bearing <= 292.5)
			{
				return CompassDirection.W;
			}
			else if (bearing >= 292.5 && bearing <= 337.5)
			{
				return CompassDirection.NW;
			}
            else
            {
				return CompassDirection.N;
            }
		}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
		public static double DegreeBearing(double lon1, double lat1, double lon2, double lat2)
		{
			var dLon = ToRadians(lon2 - lon1);
			var dPhi = Math.Log(Math.Tan(ToRadians(lat2) / 2 + Math.PI / 4) / Math.Tan(ToRadians(lat1) / 2 + Math.PI / 4));
			if (Math.Abs(dLon) > Math.PI) dLon = dLon > 0 ? -(2 * Math.PI - dLon) : (2 * Math.PI + dLon);
			return ToBearing(Math.Atan2(dLon, dPhi));
		}


[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
		public static double ToBearing(double radians)
		{
			// convert radians to degrees (as bearing: 0...360)
			return (ToDegrees(radians) + 360) % 360;
		}

See also: StackOverflow

juliusfriedman avatar Nov 25 '20 04:11 juliusfriedman