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); }
/// <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()); }