Exemple #1
0
        public async Task <IEnumerable <GeoClusterLocation> > GetGeoLocationClustersAsync(
            GetGeoLocationClustersRequest request,
            CancellationToken cancellationToken)
        {
            IEnumerable <MediaGeoLocation> medias = await _mediaStore.FindMediaInGeoBoxAsync(
                request.Box,
                100000,
                cancellationToken);

            var clusters = new List <GeoClusterLocation>();

            if (medias.Count() < 500 && request.Precision > 10)
            {
                //Add every item as cluster
                foreach (MediaGeoLocation media in medias)
                {
                    clusters.Add(new GeoClusterLocation()
                    {
                        Hash = GeoHash.Encode(
                            media.Coordinates.Latitude,
                            media.Coordinates.Longitude),

                        Coordinates = media.Coordinates,
                        Id          = media.Id,
                        Count       = 1
                    });
                }
            }
            else
            {
                medias.ToList().ForEach(x => x.GeoHash = x.GeoHash.Substring(0, request.Precision));
                IEnumerable <IGrouping <string, MediaGeoLocation> > grouped = medias
                                                                              .GroupBy(x => x.GeoHash);

                foreach (IGrouping <string, MediaGeoLocation>?group in grouped)
                {
                    GeohashDecodeResult decoded = GeoHash.Decode(group.Key);
                    var cluster = new GeoClusterLocation
                    {
                        Hash        = group.Key,
                        Count       = group.Count(),
                        Coordinates = new GeoCoordinate
                        {
                            Latitude  = decoded.Coordinates.Lat,
                            Longitude = decoded.Coordinates.Lon
                        }
                    };
                    if (group.Count() == 1)
                    {
                        cluster.Id = group.First().Id;
                    }
                    clusters.Add(cluster);
                }
            }

            return(clusters);
        }
Exemple #2
0
        /// <summary>
        /// Bounding Circle
        /// Get all the hashString covered by the circle in numberOfChars
        /// </summary>
        /// <param name="latitude">latitude of center point</param>
        /// <param name="longitude">longitude of center point</param>
        /// <param name="radius">radius in meters</param>
        /// <param name="numberOfChars">number of characters of hash string</param>
        /// <returns>hash string array</returns>
        public static string[] Bcircle(double latitude, double longitude, double radius, int numberOfChars = 9)
        {
            var    hashList   = new List <string>();
            string hashCenter = GeoHash.Encode(latitude, longitude, numberOfChars);

            hashList.Add(hashCenter);

            GeohashDecodeResult latLon = GeoHash.Decode(hashCenter);

            // Find left and right end
            // Find west(left) end
            Coordinates leftCoor = DistanceToPoint(latitude, longitude, radius, 270);
            string      hashLeft = GeoHash.Encode(leftCoor.Lat, leftCoor.Lon, numberOfChars);

            NGeoHash.BoundingBox boxLeft = GeoHash.DecodeBbox(hashLeft);

            // Find east(right) end
            Coordinates rightCoor = DistanceToPoint(latitude, longitude, radius, 90);
            string      hashRight = GeoHash.Encode(rightCoor.Lat, rightCoor.Lon, numberOfChars);

            NGeoHash.BoundingBox boxRight = GeoHash.DecodeBbox(hashRight);

            // Find steps(from left to right)
            double perLon  = latLon.Error.Lon * 2; // box size(in degree) on west-east direction
            var    lonStep = Math.Round((boxRight.Minimum.Lon - boxLeft.Minimum.Lon) / perLon);

            double perLat = latLon.Error.Lat * 2; // box size(in dgree) on north–south direction

            for (var lon = 0; lon <= lonStep; lon++)
            {
                // Find current box
                string currentBoxHash           = GeoHash.Neighbor(hashLeft, new[] { 0, lon });
                NGeoHash.BoundingBox currentBox = GeoHash.DecodeBbox(currentBoxHash);

                // Find north(upper) end
                // Find up neighbor
                // Check if in range
                int i = 0;
                NGeoHash.BoundingBox upBox = currentBox;
                string upBoxHash           = currentBoxHash;
                while (BoxInCircleRange(upBox, latitude, longitude, radius))
                {
                    if (!hashList.Contains(upBoxHash))
                    {
                        hashList.Add(upBoxHash);
                    }
                    //Console.WriteLine("Add+ " + upBoxHash);
                    i++;
                    upBoxHash = GeoHash.Neighbor(currentBoxHash, new[] { i, 0 });
                    upBox     = GeoHash.DecodeBbox(upBoxHash);
                }

                // Find south(down) end
                // Find steps(north to south)
                int j = 0;
                NGeoHash.BoundingBox downBox = currentBox;
                string downBoxHash           = currentBoxHash;
                while (BoxInCircleRange(downBox, latitude, longitude, radius))
                {
                    if (!hashList.Contains(downBoxHash))
                    {
                        hashList.Add(downBoxHash);
                    }
                    //Console.WriteLine("Add- " + downBoxHash);
                    j--;
                    downBoxHash = GeoHash.Neighbor(currentBoxHash, new[] { j, 0 });
                    downBox     = GeoHash.DecodeBbox(downBoxHash);
                }
            }

            // Check each point on the circle, see if covers more box
            // Find step length of radius
            double stepOfRadius = FindMinSideLength(hashCenter) * 0.9;
            // Find step of cricle, devide 360 degree to how many parts
            double stepOfCircle = 360 / (Math.PI * 2 * radius / stepOfRadius);

            for (double degree = 0; degree <= 360; degree += stepOfCircle)
            {
                Coordinates coor = DistanceToPoint(latitude, longitude, radius, degree);
                string      hash = GeoHash.Encode(coor.Lat, coor.Lon, numberOfChars);
                if (!hashList.Contains(hash))
                {
                    hashList.Add(hash);
                }
            }


            return(hashList.ToArray());
        }