This is part of the latest feature of our Advanced Sitecore Google Maps (WCAG Edition). I have added a new feature to find the nearest markers based on an address.
The caclculation is based on the approximate birds-flight distance between 2 latitude/longitude coordinates. Google Maps has a JavaScript function to give you the numbers, but since our Google Maps implementation will work without JavaScript I have to do the math in C#.
The calculation needs to return the distance in either kilometers or miles, so I have created an enumeration for this:
public enum MeasureUnits { Miles, Kilometers };
The rest is pure math and is based on an approximated earth radius of 3960 miles (or 6371 kilometers). The class is basically the same Coordinate class I used in the Google Maps Polyline Encoding article. The class is extended with the DistanceFrom function that calculates the distance to another Coordinate.
namespace PT.GoogleMaps.Core { public class Coordinate { /// <summary> /// The units of measure when calculating distance between 2 coordinates /// </summary> public enum MeasureUnits { Miles, Kilometers }; /// <summary> /// Gets or sets the latitude of the coordinate. /// </summary> public double Latitude { get; set; } /// <summary> /// Gets or sets the longitude of the coordinate. /// </summary> public double Longitude { get; set; } /// <summary> /// Initializes a new instance of the <see cref="Coordinate"/> class. /// </summary> /// <param name="latitude">The latitude.</param> /// <param name="longitude">The longitude.</param> public Coordinate(double latitude, double longitude) { Latitude = latitude; Longitude = longitude; } /// <summary> /// Calculates the approximate birds-flight distance between this coordinate and the coordinate in the parameter /// </summary> /// <param name="coordinate">The coordinate.</param> /// <param name="units">The units to measure in</param> /// <returns></returns> public double DistanceFrom(Coordinate coordinate, MeasureUnits units) { double earthRadius = (units == MeasureUnits.Miles) ? 3960 : 6371; double dLat = Deg2Rad(coordinate.Latitude - Latitude); double dLon = Deg2Rad(coordinate.Longitude - Longitude); double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(Deg2Rad(Latitude)) * Math.Cos(Deg2Rad(coordinate.Latitude)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2); double c = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a))); double d = earthRadius * c; return d; } /// <summary> /// Converts from Degrees to Radians /// </summary> /// <param name="deg">The degrees</param> /// <returns>The radians</returns> private double Deg2Rad(double deg) { return (deg * Math.PI / 180.0); } } }
Pingback: Weather-based content targeting with Sitecore DMS | Ruben's Happy Coding Paradise