private async Task <IEnumerable <Location> > GetLocationsByCoordinates(double latitude, double longitude, double?radiusInKm, string iso3Code) { string geohash = null; var locationsCount = 0; IEnumerable <Location> locations = null; const int locationsLimit = 20; var shouldSearchIteratively = !radiusInKm.HasValue; radiusInKm = radiusInKm ?? 8; //Try to get locations in radius if there are not locations in this radius, //increase it and try again until you find location or the radius exceeds the maximum allowed do { var geohashLevel = DistanceHelper.GetGeohashLevelByRadius(radiusInKm.Value); geohash = _geohasher.Encode(latitude, longitude, precision: geohashLevel); locations = await _locationRepository.GetLocationsByFilterAsync(geohash, iso3Code); if (locations.Any()) { var locationDistances = new Dictionary <Guid, double>(); foreach (var location in locations) { var distance = DistanceHelper.GetDistanceInKmBetweenTwoPoints( latitude, longitude, location.Latitude.Value, location.Longitude.Value); if (distance <= radiusInKm.Value) { locationDistances.Add(location.Id, distance); } } //Additional precise filtering locations = locations .Where(l => locationDistances.ContainsKey(l.Id)) .OrderBy(l => locationDistances[l.Id]); } locationsCount = locations.Count(); radiusInKm *= 2; } while (shouldSearchIteratively && radiusInKm.Value <= MaxRadiusInKm && locationsCount < locationsLimit); return(locations); }
public async Task <Guid[]> GetPartnerIdsInRadiusByCoordinatesAsync(double radiusInKm, double longitude, double latitude) { if (latitude < -90 || latitude > 90 || longitude < -180 || longitude > 180) { throw new ArgumentException("Invalid argument value for get near partners request"); } var geohashLevel = DistanceHelper.GetGeohashLevelByRadius(radiusInKm); var geohash = _geohasher.Encode(latitude, longitude, precision: geohashLevel); var locations = await _locationRepository.GetLocationsByGeohashAsync(geohash); var result = locations .Where(l => DistanceHelper.GetDistanceInKmBetweenTwoPoints(latitude, longitude, l.Latitude.Value, l.Longitude.Value) <= radiusInKm) .Select(l => l.PartnerId) .Distinct() .ToArray(); return(result); }