2012-11-22 21:42:29 +01:00
|
|
|
|
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
|
2013-01-17 18:48:38 +01:00
|
|
|
|
// Copyright © 2013 Clemens Fischer
|
2012-05-04 12:52:20 +02:00
|
|
|
|
// Licensed under the Microsoft Public License (Ms-PL)
|
|
|
|
|
|
|
|
|
|
|
|
using System;
|
2012-08-08 20:42:06 +02:00
|
|
|
|
using System.Collections.Generic;
|
2012-12-09 22:18:31 +01:00
|
|
|
|
#if NETFX_CORE
|
2012-11-22 21:42:29 +01:00
|
|
|
|
using Windows.Foundation;
|
|
|
|
|
|
using Windows.UI.Xaml;
|
|
|
|
|
|
using Windows.UI.Xaml.Media;
|
|
|
|
|
|
#else
|
2012-04-25 22:02:53 +02:00
|
|
|
|
using System.Windows;
|
|
|
|
|
|
using System.Windows.Media;
|
|
|
|
|
|
using System.Windows.Threading;
|
2012-11-22 21:42:29 +01:00
|
|
|
|
#endif
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
|
|
|
|
|
namespace MapControl
|
|
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
internal partial class TileContainer
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
|
|
|
|
|
private const double maxScaledTileSize = 400d; // scaled tile size 200..400 units
|
|
|
|
|
|
private static double zoomLevelSwitchOffset = Math.Log(maxScaledTileSize / 256d, 2d);
|
|
|
|
|
|
|
|
|
|
|
|
private Size size;
|
|
|
|
|
|
private Point origin;
|
2012-11-22 21:42:29 +01:00
|
|
|
|
private Point offset;
|
2012-04-25 22:02:53 +02:00
|
|
|
|
private double rotation;
|
|
|
|
|
|
private double zoomLevel;
|
|
|
|
|
|
private int tileZoomLevel;
|
|
|
|
|
|
private Int32Rect tileGrid;
|
|
|
|
|
|
private readonly DispatcherTimer updateTimer;
|
2012-08-08 20:42:06 +02:00
|
|
|
|
|
|
|
|
|
|
public readonly MatrixTransform ViewportTransform = new MatrixTransform();
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
|
|
|
|
|
public TileContainer()
|
|
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
updateTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(0.5) };
|
|
|
|
|
|
updateTimer.Tick += UpdateTiles;
|
2012-04-25 22:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2012-08-08 20:42:06 +02:00
|
|
|
|
public void AddTileLayers(int index, IEnumerable<TileLayer> tileLayers)
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
var tileLayerTransform = GetTileLayerTransformMatrix();
|
2012-08-08 20:42:06 +02:00
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
foreach (var tileLayer in tileLayers)
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
if (index < Children.Count)
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
Children.Insert(index, tileLayer);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Children.Add(tileLayer);
|
2012-04-25 22:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
index++;
|
2013-01-03 15:33:46 +01:00
|
|
|
|
tileLayer.SetTransformMatrix(tileLayerTransform);
|
2012-08-08 20:42:06 +02:00
|
|
|
|
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
public void RemoveTileLayers(int index, int count)
|
2012-08-08 20:42:06 +02:00
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
while (count-- > 0)
|
2012-08-08 20:42:06 +02:00
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
((TileLayer)Children[index]).ClearTiles();
|
|
|
|
|
|
Children.RemoveAt(index);
|
2012-04-25 22:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-08-08 20:42:06 +02:00
|
|
|
|
public void ClearTileLayers()
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-08-08 20:42:06 +02:00
|
|
|
|
foreach (TileLayer tileLayer in Children)
|
|
|
|
|
|
{
|
|
|
|
|
|
tileLayer.ClearTiles();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Children.Clear();
|
2012-04-25 22:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2012-08-08 20:42:06 +02:00
|
|
|
|
public double SetViewportTransform(double mapZoomLevel, double mapRotation, Point mapOrigin, Point viewportOrigin, Size viewportSize)
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
var scale = Math.Pow(2d, zoomLevel) * 256d / 360d;
|
|
|
|
|
|
var oldMapOriginX = (origin.X - offset.X) / scale - 180d;
|
2012-11-06 19:49:29 +01:00
|
|
|
|
|
|
|
|
|
|
if (zoomLevel != mapZoomLevel)
|
|
|
|
|
|
{
|
|
|
|
|
|
zoomLevel = mapZoomLevel;
|
|
|
|
|
|
scale = Math.Pow(2d, zoomLevel) * 256d / 360d;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-04-25 22:02:53 +02:00
|
|
|
|
rotation = mapRotation;
|
2012-05-04 12:52:20 +02:00
|
|
|
|
size = viewportSize;
|
|
|
|
|
|
origin = viewportOrigin;
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
|
|
|
|
|
offset.X = origin.X - (180d + mapOrigin.X) * scale;
|
|
|
|
|
|
offset.Y = origin.Y - (180d - mapOrigin.Y) * scale;
|
|
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
ViewportTransform.Matrix = GetTransformMatrix(new Matrix(1d, 0d, 0d, -1d, 180d, 180d), scale);
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
2012-11-06 19:49:29 +01:00
|
|
|
|
if (Math.Sign(mapOrigin.X) == Math.Sign(oldMapOriginX))
|
|
|
|
|
|
{
|
2013-01-03 15:33:46 +01:00
|
|
|
|
var tileLayerTransform = GetTileLayerTransformMatrix();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (TileLayer tileLayer in Children)
|
|
|
|
|
|
{
|
|
|
|
|
|
tileLayer.SetTransformMatrix(tileLayerTransform);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
updateTimer.Start();
|
2012-11-06 19:49:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// immediately handle map origin leap when map center moves across the date line
|
|
|
|
|
|
UpdateTiles(this, EventArgs.Empty);
|
|
|
|
|
|
}
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
|
|
|
|
|
return scale;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
private Matrix GetTileLayerTransformMatrix()
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
// Calculates the TileLayer VisualTransform or RenderTransform matrix
|
|
|
|
|
|
// with origin at tileGrid.X and tileGrid.Y to minimize rounding errors.
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
return GetTransformMatrix(
|
|
|
|
|
|
new Matrix(1d, 0d, 0d, 1d, tileGrid.X * 256d, tileGrid.Y * 256d),
|
|
|
|
|
|
Math.Pow(2d, zoomLevel - tileZoomLevel));
|
2012-04-25 22:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
private void UpdateTiles(object sender, object e)
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2012-11-22 21:42:29 +01:00
|
|
|
|
updateTimer.Stop();
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
var zoom = (int)Math.Floor(zoomLevel + 1d - zoomLevelSwitchOffset);
|
|
|
|
|
|
var numTiles = 1 << zoom;
|
|
|
|
|
|
var transform = GetTileIndexMatrix(numTiles);
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
|
|
|
|
|
// tile indices of visible rectangle
|
2012-11-22 21:42:29 +01:00
|
|
|
|
var p1 = transform.Transform(new Point(0d, 0d));
|
|
|
|
|
|
var p2 = transform.Transform(new Point(size.Width, 0d));
|
|
|
|
|
|
var p3 = transform.Transform(new Point(0d, size.Height));
|
|
|
|
|
|
var p4 = transform.Transform(new Point(size.Width, size.Height));
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
2012-11-22 21:42:29 +01:00
|
|
|
|
var left = Math.Min(p1.X, Math.Min(p2.X, Math.Min(p3.X, p4.X)));
|
|
|
|
|
|
var right = Math.Max(p1.X, Math.Max(p2.X, Math.Max(p3.X, p4.X)));
|
|
|
|
|
|
var top = Math.Min(p1.Y, Math.Min(p2.Y, Math.Min(p3.Y, p4.Y)));
|
|
|
|
|
|
var bottom = Math.Max(p1.Y, Math.Max(p2.Y, Math.Max(p3.Y, p4.Y)));
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
|
|
|
|
|
// index ranges of visible tiles
|
2012-11-22 21:42:29 +01:00
|
|
|
|
var x1 = (int)Math.Floor(left);
|
|
|
|
|
|
var x2 = (int)Math.Floor(right);
|
|
|
|
|
|
var y1 = Math.Max((int)Math.Floor(top), 0);
|
|
|
|
|
|
var y2 = Math.Min((int)Math.Floor(bottom), numTiles - 1);
|
|
|
|
|
|
var grid = new Int32Rect(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
|
|
|
|
|
if (tileZoomLevel != zoom || tileGrid != grid)
|
|
|
|
|
|
{
|
|
|
|
|
|
tileZoomLevel = zoom;
|
|
|
|
|
|
tileGrid = grid;
|
2012-11-22 21:42:29 +01:00
|
|
|
|
var tileLayerTransform = GetTileLayerTransformMatrix();
|
2012-04-25 22:02:53 +02:00
|
|
|
|
|
2012-08-08 20:42:06 +02:00
|
|
|
|
foreach (TileLayer tileLayer in Children)
|
2012-04-25 22:02:53 +02:00
|
|
|
|
{
|
2013-01-03 15:33:46 +01:00
|
|
|
|
tileLayer.SetTransformMatrix(tileLayerTransform);
|
2012-08-08 20:42:06 +02:00
|
|
|
|
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
|
2012-04-25 22:02:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|