Example #1
0
        public ClusterGenerator(MapControl map, ControlTemplate itemTemplate)
        {
            _map         = map;
            ItemTemplate = itemTemplate;
            GenerateMapItems();

            _contractService = SimpleIoc.Default.GetInstance <IContractService>();
            _contractService.ContractRefreshed += OnContractRefreshed;
            _contractService.StationRefreshed  += OnStationRefreshed;

            // maps event
            var mapObserver = Observable.FromEventPattern(map, "CenterChanged");

            mapObserver
            .Do((e) =>
            {
                cts.Cancel();
                cts = new CancellationTokenSource();
            })
            .Throttle(throttleTime)
            .Select(async x =>
            {
                var stations = SimpleIoc.Default.GetInstance <IContractService>().GetStations();
                // some services can provide wrong values in lat or lon... just take care of it
                foreach (var station in stations.Where(s => s.Location == null))
                {
                    station.Location = new Geopoint(new BasicGeoposition {
                        Latitude = station.Latitude, Longitude = station.Longitude
                    });
                }


                await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    //mapArea = _map.GetViewArea();
                    mapLocations = _map.GetViewLocations();
                    if (mapLocations != null)
                    {
                        leftCornerLocation = mapLocations.First().Position;
                    }
                    zoomLevel = _map.ZoomLevel;

                    // TESTING only
                    //velibControls[0].SetValue(MapControl.LocationProperty, new Geopoint(new BasicGeoposition()
                    //    {
                    //        Latitude = mapArea.NorthwestCorner.Latitude,
                    //        Longitude = mapArea.NorthwestCorner.Longitude,
                    //    }));
                    //velibControls[0].ShowVelibStation();
                    //velibControls[1].SetValue(MapControl.LocationProperty, new Geopoint(new BasicGeoposition()
                    //{
                    //    Latitude = mapArea.SoutheastCorner.Latitude,
                    //    Longitude = mapArea.SoutheastCorner.Longitude,
                    //}));
                    //velibControls[1].ShowVelibStation();
                });
                //return null;
                // that could happend is the zoom is really low and the map is turned
                if (mapLocations == null)
                {
                    return(null);
                }

                var collection      = new AddRemoveCollection();
                collection.ToRemove = Items.Where(t => !MapExtensions.Contains(mapLocations, t.Latitude, t.Longitude)).ToList();
                collection.ToAdd    = stations.Where(t => !Items.Contains(t) &&
                                                     MapExtensions.Contains(mapLocations, t.Latitude, t.Longitude)).Take(MAX_CONTROLS).ToList();
                if (Items.Count > MAX_CONTROLS + collection.ToRemove.Count)
                {
                    collection.ToAdd.Clear();
                }


                // precalculate the items offset (that deffer well calculation)
                foreach (var velib in collection.ToAdd)
                {
                    velib.GetOffsetLocation2(leftCornerLocation, zoomLevel);
                }
                return(collection);
            })
            .Switch()
            .Subscribe(x =>
            {
                if (x == null)
                {
                    return;
                }
                RefreshView(x, cts.Token);
            });
        }
Example #2
0
        private async void RefreshView(AddRemoveCollection addRemoveCollection, CancellationToken token)
        {
            if (token.IsCancellationRequested)
            {
                return;
            }

            // remove out of view items
            foreach (var velib in Items.Where(t => addRemoveCollection.ToRemove.Contains(t)).ToList())
            {
                if (velib.Control != null)
                {
                    ((StationControl)velib.Control).RemoveVelib(velib);
                }
                Items.Remove(velib);
                if (token.IsCancellationRequested)
                {
                    return;
                }
            }

            if (zoomLevel > 15)
            {
                MAXDISTANCE = 1;
            }
            else
            {
                MAXDISTANCE = 100;
            }

            // refresh clusters by removing them from current cluster if required
            // and send them back to the ToAddPool to be retreated
            // (when zoom in)
            if (previousZoom < zoomLevel)
            {
                foreach (var control in StationControls.Where(t => t.Stations.Count > 1))
                {
                    foreach (var velib in control.Stations.ToList().Where(t => t.GetOffsetLocation2(leftCornerLocation, zoomLevel)
                                                                          .GetDistanceTo(control.GetOffsetLocation2(leftCornerLocation, zoomLevel)) > MAXDISTANCE).ToList())
                    {
                        addRemoveCollection.ToAdd.Add(velib);
                        Items.Remove(velib);
                        control.RemoveVelib(velib);
                        await Task.Delay(1);

                        if (token.IsCancellationRequested)
                        {
                            return;
                        }
                    }
                }
            }
            // (when dezoom)
            // refresh clusters clustering clusters
            if (previousZoom > zoomLevel)
            {
                foreach (var alreadyAddedVelib in Items.ToList())
                {
                    if (alreadyAddedVelib.Control == null)
                    {
                        continue;
                    }

                    Point locationOffset = alreadyAddedVelib.GetOffsetLocation2(leftCornerLocation, zoomLevel);
                    foreach (var alreadyAddedVelib2 in Items.Where(t => t.GetHashCode() != alreadyAddedVelib.GetHashCode()).ToList())
                    {
                        if (alreadyAddedVelib2.Control == null)
                        {
                            continue;
                        }
                        var    loc      = alreadyAddedVelib2.GetOffsetLocation2(leftCornerLocation, zoomLevel);
                        double distance = loc.GetDistanceTo(locationOffset);
                        if (distance < MAXDISTANCE && alreadyAddedVelib.Control != alreadyAddedVelib2.Control)
                        {
                            // add the velib the ToAdd collection to be handled again
                            addRemoveCollection.ToAdd.Add(alreadyAddedVelib2);
                            Items.Remove(alreadyAddedVelib2);
                            ((StationControl)alreadyAddedVelib2.Control).RemoveVelib(alreadyAddedVelib2);
                        }
                        if (token.IsCancellationRequested)
                        {
                            return;
                        }
                    }
                }
            }


            previousZoom = zoomLevel;

            foreach (var station in addRemoveCollection.ToAdd)
            {
                AddToCollection(station);
                if (token.IsCancellationRequested)
                {
                    return;
                }
            }

            var list = StationControls.Where(c => c.NeedRefresh && c.Stations.Count == 0);

            foreach (var control in StationControls.Where(c => c.NeedRefresh && c.Stations.Count == 0))
            {
                await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    control.Hide();
                }
                                          );
            }
            // finalise the ui cycle
            foreach (var control in StationControls.Where(c => c.NeedRefresh && c.Stations.Count != 0))
            {
                await Task.Delay(TimeSpan.FromMilliseconds(25));

                if (token.IsCancellationRequested)
                {
                    break;
                }
                var stations = control.Stations;
                if (stations.Count == 1)
                {
                    var station = stations.FirstOrDefault();
                    if (station != null)
                    {
                        if (station.Contract.StationRefreshGranularity)
                        {
                            if (!station.IsInRefreshPool)
                            {
                                _contractService.AddStationToRefreshingPool(station);
                            }
                        }
                    }
                }
                var location = control.GetLocation();
                await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => control.FinaliseUiCycle(dispatcher, location, token));
            }

            foreach (var station in Items)
            {
                // reinit calculated location to refresh it next UI cycle
                station.OffsetLocation = null;
                var control = station.Control as StationControl;
                if (control != null)
                {
                    control.Location         = null;
                    control.OffsetLocation.X = 0;
                }
            }
        }