示例#1
0
        /// <summary>
        /// Gets the distance between two coordinates using the Haversine formula
        /// </summary>
        /// <param name="source">The source coordinate</param>
        /// <param name="destination">The destination coordinate</param>
        /// <param name="distanceType">The unit of measure for the distance, this defaults to KILOMETERS</param>
        /// <returns>The distance between the two coordinates</returns>
        public static double GetDistance(ICoordinate source, ICoordinate destination, DistanceType distanceType = DistanceType.KILOMETERS)
        {
            double Radius = 0;

            switch (distanceType)
            {
            case DistanceType.KILOMETERS:
            {
                Radius = EarthRadiusInKilometers;
                break;
            }

            case DistanceType.METERS:
            {
                Radius = EarthRadiusInKilometers * 1000;
                break;
            }

            case DistanceType.MILES:
            {
                Radius = EarthRadiusInMiles;
                break;
            }
            }

            double DeltaLatitude  = DegreeToRadian(destination.GetLatitude().DecimalDegrees - source.GetLatitude().DecimalDegrees);
            double DeltaLongitude = DegreeToRadian(destination.GetLongitude().DecimalDegrees - source.GetLongitude().DecimalDegrees);
            double A = Math.Pow(Math.Sin(DeltaLatitude / 2), 2) +
                       Math.Cos(DegreeToRadian(source.GetLatitude().DecimalDegrees)) * Math.Cos(DegreeToRadian(destination.GetLatitude().DecimalDegrees)) *
                       Math.Pow(Math.Sin(DeltaLongitude / 2), 2);
            double C        = 2 * Math.Atan2(Math.Sqrt(A), Math.Sqrt(1 - A));
            double Distance = C * Radius;

            return(Distance);
        }
示例#2
0
        /// <summary>
        /// Gets the initial bearing from one geocoordinate to another based on the Haversine formula
        /// </summary>
        /// <param name="source">The source coordinate</param>
        /// <param name="destination">The destination coordinate</param>
        /// <returns>The bearing from source to destination in degrees</returns>
        public static double GetInitialBearing(ICoordinate source, ICoordinate destination)
        {
            double Lat1           = DegreeToRadian(source.GetLatitude().DecimalDegrees);
            double Lat2           = DegreeToRadian(destination.GetLatitude().DecimalDegrees);
            double DeltaLongitude = DegreeToRadian(destination.GetLongitude().DecimalDegrees) - DegreeToRadian(source.GetLongitude().DecimalDegrees);

            double Y = Math.Cos(Lat2) * Math.Sin(DeltaLongitude);
            double X = Math.Cos(Lat1) * Math.Sin(Lat2) - Math.Sin(Lat1) * Math.Cos(Lat2) * Math.Cos(DeltaLongitude);

            // Multiply degrees per radian
            return((RadianToDegree(Math.Atan2(Y, X)) + 360) % 360);
        }
示例#3
0
        /// <summary>
        /// Gets the distance between two coordinates using a rhumb line
        /// </summary>
        /// <param name="source">The source coordinate</param>
        /// <param name="destination">The destination coordinate</param>
        /// <param name="distanceType">The unit of measure for the distance, this defaults to KILOMETERS</param>
        /// <returns>The distance between the two coordinates</returns>
        public static double GetRhumbDistance(ICoordinate source, ICoordinate destination, DistanceType distanceType = DistanceType.KILOMETERS)
        {
            double Radius = 0;

            switch (distanceType)
            {
            case DistanceType.KILOMETERS:
            {
                Radius = EarthRadiusInKilometers;
                break;
            }

            case DistanceType.METERS:
            {
                Radius = EarthRadiusInKilometers * 1000;
                break;
            }

            case DistanceType.MILES:
            {
                Radius = EarthRadiusInMiles;
                break;
            }
            }

            double Lat1           = DegreeToRadian(source.GetLatitude().DecimalDegrees);
            double Lat2           = DegreeToRadian(destination.GetLatitude().DecimalDegrees);
            double DeltaLatitude  = DegreeToRadian(destination.GetLatitude().DecimalDegrees - source.GetLatitude().DecimalDegrees);
            double DeltaLongitude = DegreeToRadian(Math.Abs(destination.GetLongitude().DecimalDegrees - source.GetLongitude().DecimalDegrees));

            double DeltaPhi = Math.Log(Math.Tan(Lat2 / 2 + Math.PI / 4) / Math.Tan(Lat1 / 2 + Math.PI / 4));
            double Q        = Math.Cos(Lat1);

            if (DeltaPhi != 0)
            {
                Q = DeltaLatitude / DeltaPhi;  // E-W line gives DeltaPhi=0
            }

            // if DeltaLongitude over 180° take shorter rhumb across 180° meridian
            if (DeltaLongitude > Math.PI)
            {
                DeltaLongitude = 2 * Math.PI - DeltaLongitude;
            }

            double Distance = Math.Sqrt(Math.Pow(DeltaLatitude, 2) + Math.Pow(Q, 2) * Math.Pow(DeltaLongitude, 2)) * Radius;

            return(Distance);
        }
示例#4
0
        /// <summary>
        /// Gets the bearing from one latitude/longitude coordinate to another based on the Rhumb formula
        /// </summary>
        /// <param name="source">The source coordinate</param>
        /// <param name="destination">The destination coordinate</param>
        /// <returns>The bearing from source to destination in degrees</returns>
        public static double GetRhumbBearing(ICoordinate source, ICoordinate destination)
        {
            double Lat1           = DegreeToRadian(source.GetLatitude().DecimalDegrees);
            double Lat2           = DegreeToRadian(destination.GetLatitude().DecimalDegrees);;
            double DeltaLongitude = DegreeToRadian(destination.GetLongitude().DecimalDegrees - source.GetLongitude().DecimalDegrees);

            double X = Math.Log(Math.Tan(Lat2 / 2 + Math.PI / 4) / Math.Tan(Lat1 / 2 + Math.PI / 4));

            if (Math.Abs(DeltaLongitude) > Math.PI)
            {
                DeltaLongitude = (DeltaLongitude > 0) ? -(2 * Math.PI - DeltaLongitude) : (2 * Math.PI + DeltaLongitude);
            }

            double Bearing = Math.Atan2(DeltaLongitude, X);

            return((RadianToDegree(Bearing) + 360) % 360);
        }
示例#5
0
        /// <summary>
        /// Finds the destination from a source using a rhumb line
        /// </summary>
        /// <param name="source">The source coordinate</param>
        /// <param name="bearing">The bearing to the destination in degrees</param>
        /// <param name="distance">The distance away from the source</param>
        /// <param name="distanceType">The unit of measure that the distance is provided in</param>
        /// <returns>The destination</returns>
        public static ICoordinate FindRhumbDestination(ICoordinate source, double bearing, double distance, DistanceType distanceType)
        {
            double DistanceRatio = distance / GetRadius(distanceType);

            double SourceLatitude  = DegreeToRadian(source.GetLatitude().DecimalDegrees);
            double SourceLongitude = DegreeToRadian(source.GetLongitude().DecimalDegrees);

            bearing = DegreeToRadian(bearing);

            double DestinationLatitude = SourceLatitude + (DistanceRatio * Math.Cos(bearing));

            double Delta = Math.Log(Math.Tan((Math.PI / 4) + (DestinationLatitude / 2)) / Math.Tan((Math.PI / 4) + (SourceLatitude / 2)));

            double Q = (DestinationLatitude - SourceLatitude) / Delta;

            double ShortestRoute = DistanceRatio * Math.Sin(bearing) / Q;

            double DestinationLongitude = SourceLongitude + ShortestRoute;

            return(new GeoCoordinate(RadianToDegree(DestinationLatitude), RadianToDegree(DestinationLongitude)));
        }
示例#6
0
        /// <summary>
        /// Finds the destination geocoordinate given a source coordinate, bearing, and distance
        /// </summary>
        /// <param name="source">The source coordinate</param>
        /// <param name="bearing">The direction of travel from the source in degrees</param>
        /// <param name="distance">The distance traveled</param>
        /// <param name="distanceType">The unit of measure that the distance is provided in</param>
        /// <returns>The destination geocoordinate</returns>
        public static ICoordinate FindDestination(ICoordinate source, double bearing, double distance, DistanceType distanceType)
        {
            double Radius = GetRadius(distanceType);

            double Latitude  = DegreeToRadian(source.GetLatitude().DecimalDegrees);
            double Longitude = DegreeToRadian(source.GetLongitude().DecimalDegrees);

            bearing = DegreeToRadian(bearing);

            double DestinationLatitude = RadianToDegree(Math.Asin(
                                                            Math.Sin(Latitude) * Math.Cos(distance / Radius) +
                                                            Math.Cos(Latitude) * Math.Sin(distance / Radius) * Math.Cos(bearing)
                                                            ));

            double DestinationLongitude = RadianToDegree(Longitude + Math.Atan2(
                                                             Math.Sin(bearing) * Math.Sin(distance / Radius) * Math.Cos(Latitude),
                                                             Math.Cos(distance / Radius) - Math.Sin(Latitude) * Math.Sin(DegreeToRadian(DestinationLatitude))
                                                             ));

            return(new GeoCoordinate(DestinationLatitude, ((DestinationLongitude + 540) % 360) - 180));
        }
示例#7
0
        public void HaversineDestination()
        {
            // ARRANGE
            GeoCoordinate Source      = new GeoCoordinate(40.7486, 5.4253);
            GeoCoordinate Destination = new GeoCoordinate(58.3838, 3.01412);

            // ACT
            ICoordinate CalculatedDestination = Source.FindDestination(355.84047394177765, 1967.0898177084771, DistanceType.KILOMETERS);

            // ASSERT
            Assert.Equal(Math.Round(Destination.Latitude.DecimalDegrees, 2), Math.Round(CalculatedDestination.GetLatitude().DecimalDegrees, 2));
            Assert.Equal(Math.Round(Destination.Longitude.DecimalDegrees, 2), Math.Round(CalculatedDestination.GetLongitude().DecimalDegrees, 2));
        }
示例#8
0
        public void RhumbDestination()
        {
            // ARRANGE
            GeoCoordinate Source      = new GeoCoordinate(40.7486, 5.4253);
            GeoCoordinate Destination = new GeoCoordinate(58.3838, 3.01412);

            // ACT
            ICoordinate CalculatedDestination = Source.FindRhumbDestination(355, 1967, DistanceType.KILOMETERS);

            // ASSERT
            Assert.Equal(Math.Round(Destination.GetLatitude().DecimalDegrees, 2), Math.Round(CalculatedDestination.GetLatitude().DecimalDegrees, 2));
            Assert.Equal(Math.Round(Destination.GetLongitude().DecimalDegrees, 2), Math.Round(CalculatedDestination.GetLongitude().DecimalDegrees, 2));
        }