public static List <Tuple <string, string> > GeohashQueries(Geolocation center, double radius)
        {
            GeopointService.ValidateGeopoint(center);
            var queryBits        = Math.Max(1, BoundingBoxBits(center, radius));
            var geohashPrecision = queryBits / BITS_PER_CHAR;
            var coordinates      = BoundingBoxCoordinates(center, radius);
            var queries          = coordinates.Select((coordinate) =>
            {
                return(GeohashQuery(GeoHash.Encode(coordinate.Lat, coordinate.Lon, geohashPrecision), queryBits));
            });

            // remove duplicates
            return(queries.ToHashSet().ToList());
        }
        public static double Distance(Geolocation point1, Geolocation point2)
        {
            GeopointService.ValidateGeopoint(point1);
            GeopointService.ValidateGeopoint(point2);

            var R  = 6371e3; // metres
            var φ1 = DegreesToRadians(point1.Latitude);
            var φ2 = DegreesToRadians(point2.Latitude);
            var Δφ = DegreesToRadians(point2.Latitude - point1.Latitude);
            var Δλ = DegreesToRadians(point2.Longitude - point1.Longitude);

            var a = Math.Sin(Δφ / 2) * Math.Sin(Δφ / 2) +
                    Math.Cos(φ1) * Math.Cos(φ2) *
                    Math.Sin(Δλ / 2) * Math.Sin(Δλ / 2);
            var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));

            var d = R * c;

            return(d);
        }