/Main/src/DynamicDataDisplay.Maps/Charts/NewMap.cs
C# | 613 lines | 503 code | 99 blank | 11 comment | 76 complexity | 443c320682ccfb99a7bfd01c264b26cb MD5 | raw file
Possible License(s): CC-BY-SA-3.0
- using System;
- using System.Collections.Specialized;
- using System.ComponentModel;
- using System.Diagnostics;
- using System.Globalization;
- using System.Linq;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Input;
- using System.Windows.Markup;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
- using Microsoft.Research.DynamicDataDisplay;
- using Microsoft.Research.DynamicDataDisplay.Charts.Navigation;
- using Microsoft.Research.DynamicDataDisplay.Maps.Servers.Network;
- using Microsoft.Research.DynamicDataDisplay.ViewportConstraints;
- using Microsoft.Research.DynamicDataDisplay.Maps;
- using System.Collections.Generic;
- using Microsoft.Research.DynamicDataDisplay.Common;
- using Microsoft.Research.DynamicDataDisplay.Maps.Charts;
- using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
-
-
- namespace Microsoft.Research.DynamicDataDisplay.Charts.Maps
- {
- [ContentProperty("SourceTileServer")]
- public class NewMap : FrameworkElement, IPlotterElement
- {
- public NewMap()
- {
- server.ImageLoaded += OnTileLoaded;
- server.SourceServerChanged += OnNetworkServerChanged;
-
- #if DEBUG
- drawDebugBounds = false;
- #endif
- }
-
- private TileProvider tileProvider = new MapTileProvider();
- public TileProvider TileProvider
- {
- get { return tileProvider; }
- set
- {
- if (value == null)
- throw new ArgumentNullException("value");
- tileProvider = value;
- }
- }
-
- private readonly TileServerSystem server = new TileServerSystem();
- public TileServerSystem TileSystem
- {
- get { return server; }
- }
-
- [NotNull]
- public SourceTileServer SourceTileServer
- {
- get { return server.SourceServer; }
- set { server.SourceServer = value; }
- }
-
- public TileSystemMode Mode
- {
- get { return server.Mode; }
- set { server.Mode = value; }
- }
-
- public IWriteableTileServer FileTileServer
- {
- get { return server.FileServer; }
- set { server.FileServer = value; }
- }
-
- private readonly ViewportHostPanel panel = new ViewportHostPanel();
- public ViewportHostPanel Panel
- {
- get { return panel; }
- }
-
- protected virtual void OnTileLoaded(object sender, TileLoadResultEventArgs e)
- {
- if (e.Result == TileLoadResult.Success)
- {
- DataRect tileBounds = tileProvider.GetTileBounds(e.ID);
-
- bool containsInDrawn = drawnBounds.Contains(tileBounds) || drawnBounds.IsEmpty;
- bool shouldDraw = containsInDrawn && !invalidatePending && e.ID.Level <= tileProvider.Level;
- if (shouldDraw)
- {
- DrawImage(e.Image, tileBounds, e.ID);
- }
- }
- }
-
- private int tileWidth = 256;
- private int tileHeight = 256;
- protected virtual void OnNetworkServerChanged(object sender, ValueChangedEventArgs<SourceTileServer> e)
- {
- if (e.PreviousValue != null)
- {
- RemoveLogicalChild(e.PreviousValue);
- }
- if (e.CurrentValue != null)
- {
- AddLogicalChild(e.CurrentValue);
- }
-
- SourceTileServer networkServer = server.SourceServer;
- if (networkServer != null)
- {
- tileProvider.MinLevel = networkServer.MinLevel;
- tileProvider.MaxLevel = networkServer.MaxLevel;
-
- MapTileProvider mapProvider = tileProvider as MapTileProvider;
- if (mapProvider != null)
- {
- mapProvider.MaxLatitude = networkServer.MaxLatitude;
- }
- tileWidth = networkServer.TileWidth;
- tileHeight = networkServer.TileHeight;
- }
-
- BeginInvalidateVisual();
- }
-
- private bool drawDebugBounds = false;
- public bool DrawDebugBounds
- {
- get { return drawDebugBounds; }
- set { drawDebugBounds = value; }
- }
-
- private readonly Pen debugBoundsPen = new Pen(Brushes.Red.MakeTransparent(0.5), 1);
-
- bool showsWholeMap = false;
- DataRect drawnBounds = DataRect.Empty;
- DataRect visibleBounds;
- bool invalidatePending = false;
- bool rendering = false;
- protected void OnRender()
- {
- if (DesignerProperties.GetIsInDesignMode(this))
- return;
-
- if (plotter == null)
- return;
-
- panel.Children.Clear();
-
- freeChildren = new List<MapElement>(panel.Children.Count);
- for (int i = 0; i < panel.Children.Count; i++)
- {
- freeChildren.Add((MapElement)panel.Children[i]);
- }
-
- rendering = true;
- invalidatePending = false;
-
- var transform = plotter.Viewport.Transform;
- Rect output = plotter.Viewport.Output;
- DataRect visible = plotter.Viewport.Visible;
- visibleBounds = visible;
-
- drawnBounds = DataRect.Empty;
-
- var tileInfos = GetVisibleTiles();
-
- var lowerTilesList = GetLoadedLowerTiles(tileInfos);
- // displaying lower tiles
- foreach (var tile in lowerTilesList)
- {
- if (server.IsLoaded(tile))
- {
- var bmp = server[tile];
- DataRect visibleRect = tileProvider.GetTileBounds(tile);
- DrawImage(bmp, visibleRect, tile);
- }
- else
- {
- server.BeginLoadImage(tile);
- }
- }
-
- int count = 0;
- foreach (var tileInfo in tileInfos)
- {
- drawnBounds.Union(tileInfo.VisibleBounds);
-
- count++;
- if (server.IsLoaded(tileInfo.Tile))
- {
- var bmp = server[tileInfo.Tile];
- DrawImage(bmp, tileInfo.VisibleBounds, tileInfo.Tile);
- }
- else
- {
- server.BeginLoadImage(tileInfo.Tile);
- }
- }
- showsWholeMap = count == MapTileProvider.GetTotalTilesCount(tileProvider.Level);
-
- foreach (var item in freeChildren)
- {
- panel.Children.Remove(item);
- pool.Put(item);
- }
-
- foreach (MapElement item in panel.Children)
- {
- if (item.Bitmap == null)
- {
- panel.Children.Remove(item);
- pool.Put(item);
- }
- }
-
- rendering = false;
-
- Debug.WriteLine("Drawn " + Environment.TickCount);
- }
-
- private List<MapElement> freeChildren = new List<MapElement>();
- private readonly ResourcePool<MapElement> pool = new ResourcePool<MapElement>();
- private void DrawImage(BitmapSource bmp, DataRect bounds, TileIndex id)
- {
- MapElement element = null;
- bool onPanel = false;
- if (freeChildren.Count > 0)
- {
- element = (MapElement)freeChildren[freeChildren.Count - 1];
- freeChildren.RemoveAt(freeChildren.Count - 1);
- onPanel = true;
- }
- else
- {
- element = pool.GetOrCreate();
- }
-
- element.Bitmap = bmp;
- ViewportPanel.SetViewportBounds(element, bounds);
- System.Windows.Controls.Panel.SetZIndex(element, (int)id.Level);
-
- if (!onPanel)
- {
- panel.Children.Add(element);
- panel.InvalidateMeasure();
- }
- }
-
- protected virtual DataRect Transform(DataRect visibleRect)
- {
- return visibleRect;
- }
-
- protected virtual DataRect TransformRegion(DataRect visibleRect)
- {
- return visibleRect;
- }
-
- protected List<VisibleTileInfo> GetVisibleTiles()
- {
- var transform = plotter.Viewport.Transform;
- Rect output = plotter.Viewport.Output;
- DataRect visible = plotter.Viewport.Visible;
-
- var tileInfos = (from tile in tileProvider.GetTilesForRegion(TransformRegion(visible), tileProvider.Level)
- let visibleRect = Transform(tileProvider.GetTileBounds(tile))
- let screenRect = visibleRect.ViewportToScreen(transform)
- where output.IntersectsWith(screenRect)
- select new VisibleTileInfo { Tile = tile, ScreenBounds = screenRect, VisibleBounds = visibleRect }).ToList();
-
- if (tileInfos.Count > MapTileProvider.GetTotalTilesCount(tileProvider.Level))
- {
- //Debugger.Break();
- }
-
- return tileInfos;
- }
-
- protected virtual IEnumerable<TileIndex> GetLoadedLowerTiles(IEnumerable<VisibleTileInfo> visibleTiles)
- {
- Set<TileIndex> result = new Set<TileIndex>();
-
- foreach (var tileInfo in visibleTiles)
- {
- if (!server.IsLoaded(tileInfo.Tile))
- {
- bool found = false;
- var tile = tileInfo.Tile;
- do
- {
- if (tile.HasLowerTile)
- {
- tile = tile.GetLowerTile();
- if (server.IsLoaded(tile) || tile.Level == 1)
- {
- found = true;
- result.TryAdd(tile);
- }
- }
- else
- {
- found = true;
- }
- }
- while (!found);
- }
- }
-
- return result.OrderBy(id => id.Level);
- }
-
- protected Rect EnlargeRect(Rect rect)
- {
- double coeff = 1 + 1.0 / tileWidth;
- return EnlargeRect(rect, coeff);
- }
-
- protected Rect EnlargeRect(Rect rect, double rectZoomCoeff)
- {
- Rect res = rect;
- res = res.Zoom(res.GetCenter(), rectZoomCoeff);
- return res;
- }
-
- private FormattedText CreateText(TileIndex tileIndex)
- {
- FormattedText text = new FormattedText(tileIndex.ToString(),
- CultureInfo.CurrentCulture,
- FlowDirection.LeftToRight, new Typeface("Arial"), 8, Brushes.Red);
- return text;
- }
-
- #region ChangesTextFormat property
-
- public bool ChangesTextFormat
- {
- get { return (bool)GetValue(ChangesTextFormatProperty); }
- set { SetValue(ChangesTextFormatProperty, value); }
- }
-
- public static readonly DependencyProperty ChangesTextFormatProperty = DependencyProperty.Register(
- "ChangesTextFormat",
- typeof(bool),
- typeof(NewMap),
- new FrameworkPropertyMetadata(true, OnChangesTextFormatChanged));
-
- private static void OnChangesTextFormatChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- NewMap map = (NewMap)d;
- map.OnChangesTextFormatChanged();
- }
-
- private void OnChangesTextFormatChanged()
- {
- // do nothing if disconnected
- if (plotter == null)
- return;
-
- if (ChangesTextFormat)
- {
- plotter.Children.CollectionChanged += PlotterChildren_CollectionChanged;
- ChangeTextFormat();
- }
- else
- {
- plotter.Children.CollectionChanged -= PlotterChildren_CollectionChanged;
- RevertTextFormat();
- }
- }
-
- #endregion
-
- protected virtual void BeginInvalidateVisual()
- {
- if (!rendering)
- {
- invalidatePending = true;
- OnRender();
- }
- else
- {
- Dispatcher.BeginInvoke(((Action)(() => { OnRender(); })));
- }
- }
-
- #region IPlotterElement Members
-
- Func<double, string> prevXMapping;
- Func<double, string> prevYMapping;
- PhysicalProportionsConstraint proportionsConstraint = new PhysicalProportionsConstraint(2.0);
- protected PhysicalProportionsConstraint ProportionsConstraint
- {
- get { return proportionsConstraint; }
- }
-
- MaximalSizeConstraint maxSizeConstraint = new MaximalSizeConstraint();
- protected MaximalSizeConstraint MaxSizeConstraint
- {
- get { return maxSizeConstraint; }
- }
-
- void IPlotterElement.OnPlotterAttached(Plotter plotter)
- {
- this.plotter = (Plotter2D)plotter;
- this.plotter.Viewport.PropertyChanged += Viewport_PropertyChanged;
-
- this.plotter.Viewport.Constraints.Add(maxSizeConstraint);
- this.plotter.Viewport.Constraints.Add(proportionsConstraint);
-
- this.plotter.KeyDown += new KeyEventHandler(plotter_KeyDown);
-
- if (ChangesTextFormat)
- {
- plotter.Children.CollectionChanged += PlotterChildren_CollectionChanged;
- // changing text mappings of CursorCoordinateGraph, if it exists,
- // to display text labels with degrees.
- ChangeTextFormat();
- }
-
- plotter.Children.BeginAdd(panel);
-
- OnPlotterAttached(plotter);
-
- BeginInvalidateVisual();
- }
-
- protected virtual void OnPlotterAttached(Plotter plotter)
- {
- }
-
- private void plotter_KeyDown(object sender, KeyEventArgs e)
- {
- if (e.Key == Key.Q)
- {
- tileProvider.IncreaseLevel();
- BeginInvalidateVisual();
- }
- else if (e.Key == Key.W)
- {
- tileProvider.DecreaseLevel();
- BeginInvalidateVisual();
- }
- }
-
- void PlotterChildren_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
- {
- if (ChangesTextFormat)
- {
- ChangeTextFormat();
- }
- }
-
- bool changedTextFormat = false;
- private void ChangeTextFormat()
- {
- if (changedTextFormat)
- return;
-
-
- // todo discover why sometimes we arrive here from PlotterChildren_CollectionChanged when we have removed this handler from
- // plotter.Children.CollectionChanged invocation list.
- if (plotter == null)
- return;
-
- var cursorGraph = plotter.Children.OfType<CursorCoordinateGraph>().FirstOrDefault<CursorCoordinateGraph>();
- if (cursorGraph != null)
- {
- changedTextFormat = true;
-
- // saving previous text mappings
- prevXMapping = cursorGraph.XTextMapping;
- prevYMapping = cursorGraph.YTextMapping;
-
-
- // setting new text mappings
- cursorGraph.XTextMapping = value =>
- {
- if (Double.IsNaN(value))
- return "";
-
- if (-180 <= value && value <= 180)
- {
- Degree degree = Degree.CreateLongitude(value);
- return degree.ToString();
- }
- else return null;
- };
-
- cursorGraph.YTextMapping = value =>
- {
- if (Double.IsNaN(value))
- return "";
-
- var mapTileProvider = tileProvider as MapTileProvider;
- if (mapTileProvider != null)
- {
- if (mapTileProvider.MinLatitude <= value && value <= mapTileProvider.MaxLatitude)
- {
- Degree degree = Degree.CreateLatitude(value);
- return degree.ToString();
- }
- }
- return null;
- };
- }
- }
-
-
- private void Viewport_PropertyChanged(object sender, ExtendedPropertyChangedEventArgs e)
- {
- var transform = plotter.Viewport.Transform;
-
- double prevLevel = tileProvider.Level;
- UpdateLevel(transform);
-
- bool shouldRedraw = prevLevel != tileProvider.Level;
-
- if (e.PropertyName == "Visible")
- {
- DataRect currVisible = (DataRect)e.NewValue;
- shouldRedraw |= !(drawnBounds.Contains(currVisible) || showsWholeMap);
- }
- else if (e.PropertyName == "Transform") { }
-
- if (shouldRedraw)
- {
- BeginInvalidateVisual();
- }
- }
-
- protected virtual void UpdateLevel(CoordinateTransform transform)
- {
- bool ok = false;
- do
- {
- double width = tileProvider.GetTileWidth(tileProvider.Level);
- double height = tileProvider.GetTileHeight(tileProvider.Level);
-
- DataRect size = new DataRect(new Size(width, height));
- Rect onScreen = size.ViewportToScreen(transform);
-
- // todo написать нормально
- if (onScreen.Width > tileWidth * 1.45)
- {
- if (tileProvider.IncreaseLevel())
- {
- continue;
- }
- }
- else if (onScreen.Width < tileWidth / 1.45)
- {
- if (tileProvider.DecreaseLevel())
- {
- continue;
- }
- }
- ok = true;
- } while (!ok);
- }
-
- protected virtual void OnPlotterDetaching(Plotter plotter) { }
-
- void IPlotterElement.OnPlotterDetaching(Plotter plotter)
- {
- OnPlotterDetaching(plotter);
-
- visibleBounds = new Rect();
-
- this.plotter.Children.BeginRemove(panel);
- this.plotter.Viewport.PropertyChanged -= Viewport_PropertyChanged;
-
- this.plotter.Viewport.Constraints.Remove(proportionsConstraint);
- this.plotter.Viewport.Constraints.Remove(maxSizeConstraint);
-
- this.plotter.Children.CollectionChanged -= PlotterChildren_CollectionChanged;
-
- RevertTextFormat();
-
- this.plotter = null;
- }
-
- private void RevertTextFormat()
- {
- if (changedTextFormat)
- {
- // revert test mappings of CursorCoordinateGraph, if it exists.
- var cursorGraph = plotter.Children.OfType<CursorCoordinateGraph>().FirstOrDefault<CursorCoordinateGraph>();
- if (cursorGraph != null)
- {
- cursorGraph.XTextMapping = prevXMapping;
- cursorGraph.YTextMapping = prevYMapping;
- }
- changedTextFormat = false;
- }
- }
-
- private Plotter2D plotter;
- public Plotter2D Plotter
- {
- get { return plotter; }
- }
-
- Plotter IPlotterElement.Plotter
- {
- get { return plotter; }
- }
-
- #endregion
- }
- }