Utility class for coordinating the validators
        private void Calculate()
        {
            if (!CoordinateValidator.Validate(Latitude, Longitude))
            {
                throw new ArgumentException("Invalid coordinates supplied.");
            }

            double latitudeConversionFactor  = Distance / 69;
            double longitudeConversionFactor = Distance / 69 / Math.Abs(Math.Cos(Latitude.ToRadian()));

            MinLatitude = Latitude - latitudeConversionFactor;
            MaxLatitude = Latitude + latitudeConversionFactor;

            MinLongitude = Longitude - longitudeConversionFactor;
            MaxLongitude = Longitude + longitudeConversionFactor;

            // Adjust for passing over coordinate boundaries
            if (MinLatitude < -90)
            {
                MinLatitude = 90 - (-90 - MinLatitude);
            }
            if (MaxLatitude > 90)
            {
                MaxLatitude = -90 + (MaxLatitude - 90);
            }

            if (MinLongitude < -180)
            {
                MinLongitude = 180 - (-180 - MinLongitude);
            }
            if (MaxLongitude > 180)
            {
                MaxLongitude = -180 + (MaxLongitude - 180);
            }
        }
        /// <summary>
        /// Creates a new CoordinateBoundary object
        /// </summary>
        /// <param name="latitude">The origin point latitude in decimal notation</param>
        /// <param name="longitude">The origin point longitude in decimal notation</param>
        /// <param name="distance">The distance from the origin point in statute miles</param>
        public CoordinateBoundaries(double latitude, double longitude, double distance)
        {
            if (!CoordinateValidator.Validate(latitude, longitude))
            {
                throw new ArgumentException("Invalid coordinates supplied.");
            }

            _latitude  = latitude;
            _longitude = longitude;
            _distance  = distance;

            Calculate();
        }
        /// <summary>
        /// Gets the cardinal or ordinal direction from the origin point to the destination point
        /// </summary>
        /// <param name="originLatitude">The latitude of the origin location in decimal notation</param>
        /// <param name="originLongitude">The longitude of the origin location in decimal notation</param>
        /// <param name="destinationLatitude">The latitude of the destination location in decimal notation</param>
        /// <param name="destinationLongitude">The longitude of the destination location in decimal notation</param>
        /// <returns>A string value indicating the cardinal or ordinal direction from the origin to the desintation point</returns>
        public static string GetDirection(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude)
        {
            if (!CoordinateValidator.Validate(originLatitude, originLongitude))
            {
                throw new ArgumentException("Invalid origin coordinates supplied.");
            }
            if (!CoordinateValidator.Validate(destinationLatitude, destinationLongitude))
            {
                throw new ArgumentException("Invalid destination coordinates supplied.");
            }

            double bearing = GetBearing(originLatitude, originLongitude, destinationLatitude, destinationLongitude);

            if (bearing >= 337.5 || bearing <= 22.5)
            {
                return("N");
            }
            if (bearing > 22.5 && bearing <= 67.5)
            {
                return("NE");
            }
            if (bearing > 67.5 && bearing <= 112.5)
            {
                return("E");
            }
            if (bearing > 112.5 && bearing <= 157.5)
            {
                return("SE");
            }
            if (bearing > 157.5 && bearing <= 202.5)
            {
                return("S");
            }
            if (bearing > 202.5 && bearing <= 247.5)
            {
                return("SW");
            }
            if (bearing > 247.5 && bearing <= 292.5)
            {
                return("W");
            }
            if (bearing > 292.5 && bearing < 337.5)
            {
                return("NW");
            }

            return(String.Empty);
        }
Exemple #4
0
        /// <summary>
        /// Calculate the distance between two sets of coordinates.
        /// <param name="originLatitude">The latitude of the origin location in decimal notation</param>
        /// <param name="originLongitude">The longitude of the origin location in decimal notation</param>
        /// <param name="destinationLatitude">The latitude of the destination location in decimal notation</param>
        /// <param name="destinationLongitude">The longitude of the destination location in decimal notation</param>
        /// <param name="decimalPlaces">The number of decimal places to round the return value to</param>
        /// <returns>A <see cref="Double"/> value representing the distance in miles from the origin to the destination coordinate</returns>
        /// </summary>
        public static double GetDistance(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude, int decimalPlaces)
        {
            if (!CoordinateValidator.Validate(originLatitude, originLongitude))
            {
                throw new ArgumentException("Invalid origin coordinates supplied.");
            }
            if (!CoordinateValidator.Validate(destinationLatitude, destinationLongitude))
            {
                throw new ArgumentException("Invalid destination coordinates supplied.");
            }

            double radius = EarthRadiusInMiles;

            return(Math.Round(
                       radius * 2 *
                       Math.Asin(Math.Min(1,
                                          Math.Sqrt(
                                              (Math.Pow(Math.Sin(originLatitude.DiffRadian(destinationLatitude) / 2.0), 2.0) +
                                               Math.Cos(originLatitude.ToRadian()) * Math.Cos(destinationLatitude.ToRadian()) *
                                               Math.Pow(Math.Sin((originLongitude.DiffRadian(destinationLongitude)) / 2.0),
                                                        2.0))))), decimalPlaces));
        }
        /// <summary>
        /// Calculates the bearing, in degrees between two geographic points
        /// </summary>
        /// <param name="originLatitude">The latitude of the origin location in decimal notation</param>
        /// <param name="originLongitude">The longitude of the origin location in decimal notation</param>
        /// <param name="destinationLatitude">The latitude of the destination location in decimal notation</param>
        /// <param name="destinationLongitude">The longitude of the destination location in decimal notation</param>
        /// <returns>A <see cref="Double"/> value indicating the bearing from the origin to the destination</returns>
        public static double GetBearing(double originLatitude, double originLongitude, double destinationLatitude, double destinationLongitude)
        {
            if (!CoordinateValidator.Validate(originLatitude, originLongitude))
            {
                throw new ArgumentException("Invalid origin coordinates supplied.");
            }
            if (!CoordinateValidator.Validate(destinationLatitude, destinationLongitude))
            {
                throw new ArgumentException("Invalid destination coordinates supplied.");
            }

            var destinationRadian = (destinationLongitude - originLongitude).ToRadian();
            var destinationPhi    = Math.Log(Math.Tan(destinationLatitude.ToRadian() / 2 + Math.PI / 4) / Math.Tan(originLatitude.ToRadian() / 2 + Math.PI / 4));

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

            return(Math.Atan2(destinationRadian, destinationPhi).ToBearing());
        }