NetTopologySuite / ProjNet4GeoAPI

.NET Spatial Reference and Projection Engine
GNU Lesser General Public License v2.1
268 stars 81 forks source link

Bearing and Reverse bearing #39

Open eiredrake opened 5 years ago

eiredrake commented 5 years ago

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

thanks!

airbreather commented 5 years ago

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?

eiredrake commented 5 years ago

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.

juliusfriedman commented 3 years ago

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