Exemple #1
0
        /// <summary>
        ///     Filter out any points outside of the queried area from the input list.
        /// </summary>
        /// <param name="list">List of items return by Amazon DynamoDB. It may contains points outside of the actual area queried.</param>
        /// <param name="geoQueryRequest">List of items within the queried area.</param>
        /// <returns></returns>
        private IEnumerable <IDictionary <string, AttributeValue> > Filter(IEnumerable <IDictionary <string, AttributeValue> > list,
                                                                           GeoQueryRequest geoQueryRequest)
        {
            var result = new List <IDictionary <String, AttributeValue> >();

            S2LatLngRect?latLngRect    = null;
            S2LatLng?    centerLatLng  = null;
            double       radiusInMeter = 0;

            if (geoQueryRequest is QueryRectangleRequest)
            {
                latLngRect = S2Util.GetBoundingLatLngRect(geoQueryRequest);
            }
            foreach (var item in list)
            {
                var geoJson  = item[_config.GeoJsonAttributeName].S;
                var geoPoint = GeoJsonMapper.GeoPointFromString(geoJson);

                var latLng = S2LatLng.FromDegrees(geoPoint.lat, geoPoint.lng);
                if (latLngRect != null && latLngRect.Value.Contains(latLng))
                {
                    result.Add(item);
                }
                else if (centerLatLng != null && radiusInMeter > 0 &&
                         centerLatLng.Value.GetEarthDistance(latLng) <= radiusInMeter)
                {
                    result.Add(item);
                }
            }

            return(result);
        }
Exemple #2
0
        /// <summary>
        /// An utility method to get a bounding box of latitude and longitude from a given GeoQueryRequest.
        /// </summary>
        /// <param name="geoQueryRequest">It contains all of the necessary information to form a latitude and longitude box.</param>
        /// <returns></returns>
        public static S2LatLngRect GetBoundingLatLngRect(GeoQueryRequest geoQueryRequest)
        {
            if (geoQueryRequest is QueryRectangleRequest)
            {
                var queryRectangleRequest = (QueryRectangleRequest)geoQueryRequest;

                var minPoint = queryRectangleRequest.MinPoint;
                var maxPoint = queryRectangleRequest.MaxPoint;

                var latLngRect = default(S2LatLngRect);

                if (minPoint != null && maxPoint != null)
                {
                    var minLatLng = S2LatLng.FromDegrees(minPoint.Latitude, minPoint.Longitude);
                    var maxLatLng = S2LatLng.FromDegrees(maxPoint.Latitude, maxPoint.Longitude);

                    latLngRect = new S2LatLngRect(minLatLng, maxLatLng);
                }

                return(latLngRect);
            }
            else if (geoQueryRequest is QueryRadiusRequest)
            {
                var queryRadiusRequest = (QueryRadiusRequest)geoQueryRequest;

                var centerPoint   = queryRadiusRequest.CenterPoint;
                var radiusInMeter = queryRadiusRequest.RadiusInMeter;

                var centerLatLng = S2LatLng.FromDegrees(centerPoint.Latitude, centerPoint.Longitude);

                var latReferenceUnit   = centerPoint.Latitude > 0.0 ? -1.0 : 1.0;
                var latReferenceLatLng = S2LatLng.FromDegrees(centerPoint.Latitude + latReferenceUnit,
                                                              centerPoint.Longitude);
                var lngReferenceUnit   = centerPoint.Longitude > 0.0 ? -1.0 : 1.0;
                var lngReferenceLatLng = S2LatLng.FromDegrees(centerPoint.Latitude, centerPoint.Longitude
                                                              + lngReferenceUnit);

                var latForRadius = radiusInMeter / centerLatLng.GetEarthDistance(latReferenceLatLng);
                var lngForRadius = radiusInMeter / centerLatLng.GetEarthDistance(lngReferenceLatLng);

                var minLatLng = S2LatLng.FromDegrees(centerPoint.Latitude - latForRadius,
                                                     centerPoint.Longitude - lngForRadius);
                var maxLatLng = S2LatLng.FromDegrees(centerPoint.Latitude + latForRadius,
                                                     centerPoint.Longitude + lngForRadius);

                return(new S2LatLngRect(minLatLng, maxLatLng));
            }

            return(S2LatLngRect.Empty);
        }
Exemple #3
0
        private async Task RunGeoQuery(GeoQueryRequest request, GeoQueryResult geoQueryResult, GeohashRange range, CancellationToken cancellationToken)
        {
            var queryRequest = request.QueryRequest.CopyQueryRequest();
            var hashKey      = S2Manager.GenerateHashKey(range.RangeMin, _config.HashKeyLength);

            var results = await _dynamoDBManager.QueryGeohashAsync(queryRequest, hashKey, range, cancellationToken).ConfigureAwait(false);

            foreach (var queryResult in results)
            {
                cancellationToken.ThrowIfCancellationRequested();

                // This is a concurrent collection
                geoQueryResult.QueryResults.Add(queryResult);

                var filteredQueryResult = Filter(queryResult.Items, request);

                // this is a concurrent collection
                foreach (var r in filteredQueryResult)
                {
                    geoQueryResult.Items.Add(r);
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// An utility method to get a bounding box of latitude and longitude from a given GeoQueryRequest.
        /// </summary>
        /// <param name="geoQueryRequest">It contains all of the necessary information to form a latitude and longitude box.</param>
        /// <returns></returns>
        public static S2LatLngRect GetBoundingLatLngRect(GeoQueryRequest geoQueryRequest)
        {
            if (geoQueryRequest is QueryRectangleRequest)
            {
                var queryRectangleRequest = (QueryRectangleRequest)geoQueryRequest;

                var minPoint = queryRectangleRequest.MinPoint;
                var maxPoint = queryRectangleRequest.MaxPoint;

                var latLngRect = default(S2LatLngRect);

                if (minPoint != null && maxPoint != null)
                {
                    var minLatLng = S2LatLng.FromDegrees(minPoint.lat, minPoint.lng);
                    var maxLatLng = S2LatLng.FromDegrees(maxPoint.lat, maxPoint.lng);

                    latLngRect = new S2LatLngRect(minLatLng, maxLatLng);
                }

                return(latLngRect);
            }
            return(S2LatLngRect.Empty);
        }
Exemple #5
0
        private async Task <GeoQueryResult> DispatchQueries(IEnumerable <GeohashRange> ranges, GeoQueryRequest geoQueryRequest, CancellationToken cancellationToken)
        {
            var geoQueryResult = new GeoQueryResult();


            var futureList = new List <Task>();

            var internalSource = new CancellationTokenSource();
            var internalToken  = internalSource.Token;
            var cts            = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, internalToken);


            foreach (var outerRange in ranges)
            {
                foreach (var range in outerRange.TrySplit(_config.HashKeyLength))
                {
                    var task = RunGeoQuery(geoQueryRequest, geoQueryResult, range, cts.Token);
                    futureList.Add(task);
                }
            }

            Exception inner = null;

            try
            {
                for (var i = 0; i < futureList.Count; i++)
                {
                    try
                    {
                        await futureList[i].ConfigureAwait(false);
                    }
                    catch (Exception e)
                    {
                        inner = e;
                        // cancel the others
                        internalSource.Cancel(true);
                    }
                }
            }
            catch (Exception ex)
            {
                inner = inner ?? ex;
                throw new ClientException("Querying Amazon DynamoDB failed.", inner);
            }


            return(geoQueryResult);
        }