Esempio n. 1
0
 /// <summary>
 /// A callback method that is used to generate a pushpin for a cluster of entities.
 /// </summary>
 /// <param name="cluster">A clustered point.</param>
 /// <returns>A pushpin that represents the clustered entities.</returns>
 public abstract ColoredPushpin RenderCluster(ClusteredPoint cluster);
Esempio n. 2
0
        private void Cluster(int zoom)
        {
            BackgroundWorker worker = new BackgroundWorker();

            worker.WorkerSupportsCancellation = true;
            worker.DoWork += (s, a) =>
            {
                _zoomLocked[zoom] = true;

                if (_clusteredData[zoom] == null)
                {
                    _clusteredData[zoom] = new List <ClusteredPoint>();
                }

                if (_entities != null && _entities.Count > 0)
                {
                    double tileZoomRatio = 256 * Math.Pow(2, zoom);
                    Point  pixel;
                    bool   IsInCluster;

                    //Itirate through the data
                    foreach (var entity in _entities)
                    {
                        IsInCluster = false;
                        pixel       = Helpers.CalculateGlobalPixel(entity.Location, tileZoomRatio);

                        foreach (var cluster in _clusteredData[zoom])
                        {
                            //See if pixel fits into any existing clusters
                            if (pixel.Y >= cluster.Top && pixel.Y <= cluster.Bottom &&
                                ((cluster.Left <= cluster.Right && pixel.X >= cluster.Left && pixel.X <= cluster.Right) ||
                                 (cluster.Left >= cluster.Right && (pixel.X >= cluster.Left || pixel.X <= cluster.Right))))
                            {
                                cluster.EntityIds.Add(entity.ID);
                                IsInCluster = true;
                                break;
                            }
                        }

                        //If entity is not in a cluster then it does not fit an existing cluster
                        if (!IsInCluster)
                        {
                            ClusteredPoint cluster = new ClusteredPoint();

                            cluster.Location  = entity.Location;
                            cluster.Left      = pixel.X - _options.ClusterRadius;
                            cluster.Right     = pixel.X + _options.ClusterRadius;
                            cluster.Top       = pixel.Y - _options.ClusterRadius;
                            cluster.Bottom    = pixel.Y + _options.ClusterRadius;
                            cluster.Zoom      = zoom;
                            cluster.EntityIds = new List <int>()
                            {
                                entity.ID
                            };

                            if (cluster.Left < 0)
                            {
                                cluster.Left += tileZoomRatio;
                            }

                            if (cluster.Right > tileZoomRatio)
                            {
                                cluster.Right -= tileZoomRatio;
                            }

                            _clusteredData[zoom].Add(cluster);
                        }
                    }
                }
            };
            worker.RunWorkerCompleted += (s, a) =>
            {
                _zoomLocked[zoom] = false;

                Render();
            };
            worker.RunWorkerAsync();
        }
        private void Cluster()
        {
            int zoom = (int)Math.Round(_map.ZoomLevel);

            if (_worker == null)
            {
                _worker = new BackgroundWorker();
                _worker.WorkerSupportsCancellation = true;
                _worker.DoWork += (s, a) =>
                {
                    if (_entities != null && _entities.Count > 0)
                    {
                        int gridSize  = _options.ClusterRadius * 2;
                        int numXCells = (int)Math.Ceiling(_map.ViewportSize.Width / gridSize);
                        int numYCells = (int)Math.Ceiling(_map.ViewportSize.Height / gridSize);

                        int numCells = numXCells * numYCells;

                        ClusteredPoint[] clusteredData = new ClusteredPoint[numCells];

                        Point pixel;
                        int   k, j, key;

                        int maxX = (int)Math.Ceiling(_map.ViewportSize.Width + _options.ClusterRadius);
                        int maxY = (int)Math.Ceiling(_map.ViewportSize.Height + _options.ClusterRadius);

                        //Itirate through the data
                        foreach (var entity in _entities)
                        {
                            if (_worker.CancellationPending)
                            {
                                a.Cancel = true;
                                break;
                            }

                            pixel = _map.LocationToViewportPoint(entity.Location);

                            //Check to see if the pin is within the bounds of the viewable map
                            if (pixel != null && pixel.X <= maxX && pixel.Y <= maxY && pixel.X >= -_options.ClusterRadius && pixel.Y >= -_options.ClusterRadius)
                            {
                                //calculate the grid position on the map of where the location is located
                                k = (int)Math.Floor(pixel.X / gridSize);
                                j = (int)Math.Floor(pixel.Y / gridSize);

                                //calculates the grid location in the array
                                key = k + j * numXCells;

                                if (key >= 0 && key < numCells)
                                {
                                    if (clusteredData[key] == null)
                                    {
                                        clusteredData[key] = new ClusteredPoint()
                                        {
                                            Location  = entity.Location,
                                            EntityIds = new List <int>()
                                            {
                                                entity.ID
                                            },
                                            Zoom = zoom
                                        };
                                    }
                                    else
                                    {
                                        clusteredData[key].EntityIds.Add(entity.ID);
                                    }
                                }
                            }
                        }

                        if (!a.Cancel)
                        {
                            a.Result = clusteredData.ToList();
                        }
                    }
                };
                _worker.RunWorkerCompleted += (s, a) =>
                {
                    if (!a.Cancelled)
                    {
                        if (a.Result != null)
                        {
                            Render(a.Result as List <ClusteredPoint>);
                        }
                        else
                        {
                            Render(null);
                        }
                    }
                    else
                    {
                        _worker.RunWorkerAsync();
                    }
                };
            }

            if (_worker != null && _worker.IsBusy && _worker.WorkerSupportsCancellation)
            {
                _worker.CancelAsync();
            }
            else
            {
                _worker.RunWorkerAsync();
            }
        }