I recently had to implement a localised search mechanism on an API.  Maths and Trigonometry aren’t my strengths it has to be said.  So I started looking online for pointers and background info.

Initially it might seem like you have to do some complicated maths to work out things like the size of the circle you’re dealing with etc.  But really the solution is very simple.  You know the starting points latitude and longitude and you also have a radius in a known unit, such as miles, meters or kilometers.  You’ll also have a dataset of potential target locations complete with their latitude and longitude points.

The only measurement you need is the distance from your starting point to a potential target location.  If that distance is less than or equal to the target location it’s within the circle designated by the radius.

The most accurate and popular algorithm for working this out is the Haversine algorithum.  The .NET framework has this built in.  The GeoCoordinate class inside the System.Device.Location namespace.

To use this:

var startingPoint = new GeoCoordinate(51.212213,-2.122312);
var targetPoint = new GeoCoordinate(52.212213,-1.122312);
var distanceInMeters = startingPoint.GetDistanceTo(targetPoint);

You can then convert the number of meters into whatever unit you would like to work with. Pretty simple really. The Haversine algorithm accounts for the curvature of the planet as well and has a very small margin of error.

You can find lots of implementations of this online, such as this one:

public static class Haversine {
  public static double calculate(double lat1, double lon1, double lat2, double lon2) {
    var R = 6372.8; // In kilometers
    var dLat = toRadians(lat2 - lat1);
    var dLon = toRadians(lon2 - lon1);
    lat1 = toRadians(lat1);
    lat2 = toRadians(lat2);
 
    var a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Sin(dLon / 2) * Math.Sin(dLon / 2) * Math.Cos(lat1) * Math.Cos(lat2);
    var c = 2 * Math.Asin(Math.Sqrt(a));
    return R * 2 * Math.Asin(Math.Sqrt(a));
  }
 
  public static double toRadians(double angle) {
    return Math.PI * angle / 180.0;
  }
}
 
void Main() {
  Console.WriteLine(String.Format("The distance between coordinates {0},{1} and {2},{3} is: {4}", 36.12, -86.67, 33.94, -118.40, Haversine.calculate(36.12, -86.67, 33.94, -118.40)));
}
 
// Returns: The distance between coordinates 36.12,-86.67 and 33.94,-118.4 is: 2887.25995060711

I would definitely recommend using the .NET version though as this will be thoroughly battle tested.

Docker Gotcha
Shell Overlay Icons - The Space Wars

Leave a Comment

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.