/// <summary>
        /// Calculate how far the point is along a track from the start-point, heading towards the end-point.
        /// <para>That is, if a perpendicular is drawn from the point to the (great circle) path, the along-track distance is the distance from the start point to where the perpendicular crosses the path.</para>
        /// </summary>
        /// <param name="pointA">The point to calculate the distance from.</param>
        /// <param name="startPoint">Start point of great circle path.</param>
        /// <param name="endPoint">End point of great circle path.</param>
        /// <param name="radius">Radius of earth.</param>
        /// <returns>The distance along great circle to point nearest point A in the same units as the radius.</returns>
        public double AlongTrackDistance(ICoordinate pointA, ICoordinate startPoint, ICoordinate endPoint, double radius)
        {
            if (pointA == null)
            {
                throw new ArgumentNullException(nameof(pointA), "The argument cannot be null.");
            }
            if (startPoint == null)
            {
                throw new ArgumentNullException(nameof(startPoint), "The argument cannot be null.");
            }
            if (endPoint == null)
            {
                throw new ArgumentNullException(nameof(endPoint), "The argument cannot be null.");
            }

            ValidateRadius(radius);

            var δ13 = startPoint.DistanceTo(pointA, radius) / radius;
            var θ13 = startPoint.BearingTo(pointA).ToRadians();
            var θ12 = startPoint.BearingTo(endPoint).ToRadians();

            var δxt = Math.Asin(Math.Sin(δ13) * Math.Sin(θ13 - θ12));

            var δat = Math.Acos(Math.Cos(δ13) / Math.Abs(Math.Cos(δxt)));

            var result = δat * Math.Sign(Math.Cos(θ12 - θ13)) * radius;

            return(result);
        }
        /// <summary>
        /// Calculate final bearing arriving at destination point from point A.
        /// <para>The final bearing will differ from the initial bearing by varying degrees according to distance and latitude.</para>
        /// </summary>
        /// <param name="pointA">The start point.</param>
        /// <param name="pointB">The end point.</param>
        /// <returns>Final bearing in degrees from north.</returns>
        public double FinalBearing(ICoordinate pointA, ICoordinate pointB)
        {
            if (pointA == null)
            {
                throw new ArgumentNullException(nameof(pointA), "The argument cannot be null.");
            }
            if (pointB == null)
            {
                throw new ArgumentNullException(nameof(pointB), "The argument cannot be null.");
            }

            // Get initial bearing from destination point to this point & reverse it by adding 180°.
            var result = (pointB.BearingTo(pointA) + 180) % 360;

            return(result);
        }