2012-11-22 21:42:29 +01:00
|
|
|
|
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
|
2012-05-04 12:52:20 +02:00
|
|
|
|
// Copyright © 2012 Clemens Fischer
|
|
|
|
|
|
// Licensed under the Microsoft Public License (Ms-PL)
|
|
|
|
|
|
|
|
|
|
|
|
using System;
|
2012-04-25 22:02:53 +02:00
|
|
|
|
using System.Collections.Generic;
|
2012-11-22 21:42:29 +01:00
|
|
|
|
using System.Linq;
|
|
|
|
|
|
#if WINRT
|
|
|
|
|
|
using Windows.UI.Xaml.Markup;
|
|
|
|
|
|
using Windows.UI.Xaml.Media;
|
|
|
|
|
|
#else
|
2012-04-25 22:02:53 +02:00
|
|
|
|
using System.Windows;
|
|
|
|
|
|
using System.Windows.Markup;
|
|
|
|
|
|
using System.Windows.Media;
|
2012-11-22 21:42:29 +01:00
|
|
|
|
#endif
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
|
|
|
|
|
namespace MapControl
|
|
|
|
|
|
{
|
2012-05-04 12:52:20 +02:00
|
|
|
|
/// <summary>
|
2012-07-03 18:03:56 +02:00
|
|
|
|
/// Fills a rectangular area with map tiles from a TileSource.
|
2012-05-04 12:52:20 +02:00
|
|
|
|
/// </summary>
|
2012-11-22 21:42:29 +01:00
|
|
|
|
#if WINRT
|
|
|
|
|
|
[ContentProperty(Name = "TileSource")]
|
|
|
|
|
|
#else
|
2012-04-25 22:02:53 +02:00
|
|
|
|
[ContentProperty("TileSource")]
|
2012-11-22 21:42:29 +01:00
|
|
|
|
#endif
|
|
|
|
|
|
public partial class TileLayer
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
public static TileLayer Default
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return new TileLayer
|
|
|
|
|
|
{
|
|
|
|
|
|
SourceName = "OpenStreetMap",
|
|
|
|
|
|
Description = "© {y} OpenStreetMap Contributors, CC-BY-SA",
|
|
|
|
|
|
TileSource = new TileSource("http://{c}.tile.openstreetmap.org/{z}/{x}/{y}.png")
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private readonly MatrixTransform transform = new MatrixTransform();
|
2012-06-24 23:42:11 +02:00
|
|
|
|
private readonly TileImageLoader tileImageLoader;
|
2012-11-06 19:49:29 +01:00
|
|
|
|
private List<Tile> tiles = new List<Tile>();
|
2012-04-25 22:02:53 +02:00
|
|
|
|
private string description = string.Empty;
|
|
|
|
|
|
private Int32Rect grid;
|
|
|
|
|
|
private int zoomLevel;
|
|
|
|
|
|
|
|
|
|
|
|
public TileLayer()
|
|
|
|
|
|
{
|
2012-06-24 23:42:11 +02:00
|
|
|
|
tileImageLoader = new TileImageLoader(this);
|
2012-04-25 22:02:53 +02:00
|
|
|
|
MinZoomLevel = 1;
|
|
|
|
|
|
MaxZoomLevel = 18;
|
2012-07-20 21:57:29 +02:00
|
|
|
|
MaxParallelDownloads = 8;
|
2012-11-22 21:42:29 +01:00
|
|
|
|
Initialize();
|
2012-04-25 22:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
partial void Initialize();
|
|
|
|
|
|
|
2012-11-04 10:16:39 +01:00
|
|
|
|
public string SourceName { get; set; }
|
2012-06-24 23:42:11 +02:00
|
|
|
|
public TileSource TileSource { get; set; }
|
2012-04-25 22:02:53 +02:00
|
|
|
|
public int MinZoomLevel { get; set; }
|
|
|
|
|
|
public int MaxZoomLevel { get; set; }
|
2012-07-20 21:57:29 +02:00
|
|
|
|
public int MaxParallelDownloads { get; set; }
|
2012-06-24 23:42:11 +02:00
|
|
|
|
public bool HasDarkBackground { get; set; }
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
|
|
|
|
|
public string Description
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return description; }
|
|
|
|
|
|
set { description = value.Replace("{y}", DateTime.Now.Year.ToString()); }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
public string TileSourceUriFormat
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return TileSource != null ? TileSource.UriFormat : string.Empty; }
|
|
|
|
|
|
set { TileSource = new TileSource(value); }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal Matrix TransformMatrix
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
get { return transform.Matrix; }
|
|
|
|
|
|
set { transform.Matrix = value; }
|
2012-04-25 22:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2012-07-11 19:56:22 +02:00
|
|
|
|
internal void UpdateTiles(int zoomLevel, Int32Rect grid)
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
|
|
|
|
|
this.grid = grid;
|
|
|
|
|
|
this.zoomLevel = zoomLevel;
|
|
|
|
|
|
|
2012-07-20 21:57:29 +02:00
|
|
|
|
tileImageLoader.CancelGetTiles();
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
2012-08-08 20:42:06 +02:00
|
|
|
|
if (TileSource != null)
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
|
|
|
|
|
SelectTiles();
|
|
|
|
|
|
RenderTiles();
|
2012-07-20 21:57:29 +02:00
|
|
|
|
tileImageLoader.BeginGetTiles(tiles);
|
2012-04-25 22:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-07-11 19:56:22 +02:00
|
|
|
|
internal void ClearTiles()
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-07-20 21:57:29 +02:00
|
|
|
|
tileImageLoader.CancelGetTiles();
|
2012-11-06 19:49:29 +01:00
|
|
|
|
tiles.Clear();
|
|
|
|
|
|
RenderTiles();
|
2012-04-25 22:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void SelectTiles()
|
|
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
var maxZoomLevel = Math.Min(zoomLevel, MaxZoomLevel);
|
|
|
|
|
|
var minZoomLevel = maxZoomLevel;
|
|
|
|
|
|
var container = TileContainer;
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
if (container != null && container.Children.IndexOf(this) == 0)
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-06-18 20:12:35 +02:00
|
|
|
|
minZoomLevel = MinZoomLevel;
|
2012-04-25 22:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
var newTiles = new List<Tile>();
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
for (var z = minZoomLevel; z <= maxZoomLevel; z++)
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
var tileSize = 1 << (zoomLevel - z);
|
|
|
|
|
|
var x1 = grid.X / tileSize;
|
|
|
|
|
|
var x2 = (grid.X + grid.Width - 1) / tileSize;
|
|
|
|
|
|
var y1 = Math.Max(0, grid.Y / tileSize);
|
|
|
|
|
|
var y2 = Math.Min((1 << z) - 1, (grid.Y + grid.Height - 1) / tileSize);
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
for (var y = y1; y <= y2; y++)
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
for (var x = x1; x <= x2; x++)
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
var tile = tiles.FirstOrDefault(t => t.ZoomLevel == z && t.X == x && t.Y == y);
|
2012-11-06 19:49:29 +01:00
|
|
|
|
|
|
|
|
|
|
if (tile == null)
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-11-06 19:49:29 +01:00
|
|
|
|
tile = new Tile(z, x, y);
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
var equivalentTile = tiles.FirstOrDefault(t => t.ImageSource != null && t.ZoomLevel == z && t.XIndex == tile.XIndex && t.Y == y);
|
|
|
|
|
|
|
|
|
|
|
|
if (equivalentTile != null)
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
// do not animate to avoid flicker when crossing date line
|
|
|
|
|
|
tile.SetImageSource(equivalentTile.ImageSource, false);
|
2012-04-25 22:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2012-11-06 19:49:29 +01:00
|
|
|
|
|
|
|
|
|
|
newTiles.Add(tile);
|
2012-04-25 22:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-11-06 19:49:29 +01:00
|
|
|
|
tiles = newTiles;
|
2012-04-25 22:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2012-06-24 23:42:11 +02:00
|
|
|
|
}
|