diff --git a/MapControl/Map.cs b/MapControl/Map.cs
index 43255cb8..528632bd 100644
--- a/MapControl/Map.cs
+++ b/MapControl/Map.cs
@@ -567,22 +567,18 @@ namespace MapControl
From = Center,
To = targetCenter,
Duration = TimeSpan.FromSeconds(0.5),
- FillBehavior = FillBehavior.Stop,
EasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseOut }
};
centerAnimation.Completed += CenterAnimationCompleted;
-
- updateTransform = false;
- Center = targetCenter;
- updateTransform = true;
-
BeginAnimation(CenterProperty, centerAnimation);
}
}
private void CenterAnimationCompleted(object sender, EventArgs eventArgs)
{
+ Center = TargetCenter;
+ BeginAnimation(CenterProperty, null);
centerAnimation = null;
}
@@ -620,22 +616,18 @@ namespace MapControl
From = ZoomLevel,
To = targetZoomLevel,
Duration = TimeSpan.FromSeconds(0.5),
- FillBehavior = FillBehavior.Stop,
EasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseOut }
};
zoomLevelAnimation.Completed += ZoomLevelAnimationCompleted;
-
- updateTransform = false;
- ZoomLevel = targetZoomLevel;
- updateTransform = true;
-
BeginAnimation(ZoomLevelProperty, zoomLevelAnimation);
}
}
private void ZoomLevelAnimationCompleted(object sender, EventArgs eventArgs)
{
+ ZoomLevel = TargetZoomLevel;
+ BeginAnimation(ZoomLevelProperty, null);
zoomLevelAnimation = null;
ResetTransformOrigin();
}
@@ -683,22 +675,18 @@ namespace MapControl
From = Heading,
By = delta,
Duration = TimeSpan.FromSeconds(0.5),
- FillBehavior = FillBehavior.Stop,
EasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseOut }
};
headingAnimation.Completed += HeadingAnimationCompleted;
-
- updateTransform = false;
- Heading = targetHeading;
- updateTransform = true;
-
BeginAnimation(HeadingProperty, headingAnimation);
}
}
private void HeadingAnimationCompleted(object sender, EventArgs eventArgs)
{
+ Heading = TargetHeading;
+ BeginAnimation(HeadingProperty, null);
headingAnimation = null;
}
diff --git a/MapControl/MapControl.csproj b/MapControl/MapControl.csproj
index 5f6c4dea..d8a3df6c 100644
--- a/MapControl/MapControl.csproj
+++ b/MapControl/MapControl.csproj
@@ -54,7 +54,6 @@
-
@@ -62,6 +61,7 @@
+
diff --git a/MapControl/MapInput.cs b/MapControl/MapInput.cs
index 6e4af765..2d878918 100644
--- a/MapControl/MapInput.cs
+++ b/MapControl/MapInput.cs
@@ -10,7 +10,7 @@ namespace MapControl
{
public partial class Map
{
- private double mouseWheelZoom = 0.25;
+ private double mouseWheelZoom = 1d;
private Point? mousePosition;
public double MouseWheelZoom
diff --git a/MapControl/Tile.cs b/MapControl/Tile.cs
index 3af625e3..4464c208 100644
--- a/MapControl/Tile.cs
+++ b/MapControl/Tile.cs
@@ -9,8 +9,6 @@ using System.Windows.Media.Animation;
namespace MapControl
{
- public enum TileLoadState { NotLoaded, Loading, Loaded };
-
internal class Tile
{
private static readonly DoubleAnimation opacityAnimation = new DoubleAnimation(0d, 1d, TimeSpan.FromSeconds(0.5), FillBehavior.Stop);
@@ -18,18 +16,16 @@ namespace MapControl
public readonly int ZoomLevel;
public readonly int X;
public readonly int Y;
- public readonly Uri Uri;
public readonly ImageBrush Brush = new ImageBrush();
- public Tile(TileSource tileSource, int zoomLevel, int x, int y)
+ public Tile(int zoomLevel, int x, int y)
{
ZoomLevel = zoomLevel;
X = x;
Y = y;
- Uri = tileSource.GetUri(XIndex, Y, ZoomLevel);
}
- public TileLoadState LoadState { get; set; }
+ public Uri Uri { get; set; }
public int XIndex
{
diff --git a/MapControl/TileImageLoader.cs b/MapControl/TileImageLoader.cs
index dca4c0c0..433074d4 100644
--- a/MapControl/TileImageLoader.cs
+++ b/MapControl/TileImageLoader.cs
@@ -28,18 +28,19 @@ namespace MapControl
internal int MaxDownloads;
internal string TileLayerName;
+ internal TileSource TileSource;
- internal int TilesPending
+ private bool IsCached
{
- get { return pendingTiles.Count; }
+ get { return !string.IsNullOrEmpty(TileCacheFolder) && !string.IsNullOrEmpty(TileLayerName); }
}
- internal void BeginDownloadTiles(ICollection tiles)
+ internal void StartDownloadTiles(ICollection tiles)
{
- ThreadPool.QueueUserWorkItem(BeginDownloadTilesAsync, new List(tiles.Where(t => t.LoadState == TileLoadState.NotLoaded)));
+ ThreadPool.QueueUserWorkItem(StartDownloadTilesAsync, new List(tiles.Where(t => t.Image == null && t.Uri == null)));
}
- internal void EndDownloadTiles()
+ internal void StopDownloadTiles()
{
lock (pendingTiles)
{
@@ -47,14 +48,13 @@ namespace MapControl
}
}
- private void BeginDownloadTilesAsync(object newTilesList)
+ private void StartDownloadTilesAsync(object newTilesList)
{
List newTiles = (List)newTilesList;
lock (pendingTiles)
{
- if (!string.IsNullOrEmpty(TileCacheFolder) &&
- !string.IsNullOrEmpty(TileLayerName))
+ if (IsCached)
{
List expiredTiles = new List(newTiles.Count);
@@ -65,7 +65,6 @@ namespace MapControl
if (image != null)
{
- tile.LoadState = TileLoadState.Loaded;
Dispatcher.BeginInvoke((Action)(() => tile.Image = image));
if (cacheExpired)
@@ -95,7 +94,7 @@ namespace MapControl
while (pendingTiles.Count > 0 && numDownloads < MaxDownloads)
{
Tile tile = pendingTiles.Dequeue();
- tile.LoadState = TileLoadState.Loading;
+ tile.Uri = TileSource.GetUri(tile.XIndex, tile.Y, tile.ZoomLevel);
numDownloads++;
ThreadPool.QueueUserWorkItem(DownloadTileAsync, tile);
@@ -109,16 +108,12 @@ namespace MapControl
if (image != null)
{
- tile.LoadState = TileLoadState.Loaded;
Dispatcher.BeginInvoke((Action)(() => tile.Image = image));
}
- else
- {
- tile.LoadState = TileLoadState.NotLoaded;
- }
lock (pendingTiles)
{
+ tile.Uri = null;
numDownloads--;
DownloadNextTiles(null);
}
@@ -134,25 +129,25 @@ namespace MapControl
{
if (Directory.Exists(tileDir))
{
- string[] tilePath = Directory.GetFiles(tileDir, string.Format("{0}.*", tile.Y));
+ string tilePath = Directory.GetFiles(tileDir, string.Format("{0}.*", tile.Y)).FirstOrDefault();
- if (tilePath.Length > 0)
+ if (tilePath != null)
{
try
{
- using (Stream fileStream = File.OpenRead(tilePath[0]))
+ using (Stream fileStream = File.OpenRead(tilePath))
{
image = BitmapFrame.Create(fileStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
- expired = File.GetLastWriteTime(tilePath[0]) + TileCacheExpiryAge <= DateTime.Now;
+ expired = File.GetLastWriteTime(tilePath) + TileCacheExpiryAge <= DateTime.Now;
- TraceInformation(expired ? "{0} - Cache Expired" : "{0} - Cached", tile.Uri);
+ TraceInformation(expired ? "{0} - Cache Expired" : "{0} - Cached", tilePath);
}
catch (Exception exc)
{
- TraceWarning("{0} - {1}", tilePath[0], exc.Message);
- File.Delete(tilePath[0]);
+ TraceWarning("{0} - {1}", tilePath, exc.Message);
+ File.Delete(tilePath);
}
}
}
@@ -191,9 +186,7 @@ namespace MapControl
string tilePath;
- if (!string.IsNullOrEmpty(TileCacheFolder) &&
- !string.IsNullOrEmpty(TileLayerName) &&
- (tilePath = TilePath(tile, decoder)) != null)
+ if (IsCached && (tilePath = TilePath(tile, decoder)) != null)
{
Directory.CreateDirectory(Path.GetDirectoryName(tilePath));
diff --git a/MapControl/TileLayer.cs b/MapControl/TileLayer.cs
index 9f6685b1..69a58ec2 100644
--- a/MapControl/TileLayer.cs
+++ b/MapControl/TileLayer.cs
@@ -35,7 +35,6 @@ namespace MapControl
MaxDownloads = 8;
}
- public TileSource TileSource { get; set; }
public bool HasDarkBackground { get; set; }
public int MinZoomLevel { get; set; }
public int MaxZoomLevel { get; set; }
@@ -46,6 +45,12 @@ namespace MapControl
set { tileImageLoader.MaxDownloads = value; }
}
+ public TileSource TileSource
+ {
+ get { return tileImageLoader.TileSource; }
+ set { tileImageLoader.TileSource = value; }
+ }
+
public bool IsCached
{
get { return isCached; }
@@ -83,68 +88,51 @@ namespace MapControl
this.grid = grid;
this.zoomLevel = zoomLevel;
- tileImageLoader.EndDownloadTiles();
+ tileImageLoader.StopDownloadTiles();
if (VisualParent != null && TileSource != null)
{
SelectTiles();
RenderTiles();
- tileImageLoader.BeginDownloadTiles(tiles);
+ tileImageLoader.StartDownloadTiles(tiles);
}
}
public void ClearTiles()
{
tiles.Clear();
- tileImageLoader.EndDownloadTiles();
- }
-
- private Int32Rect GetTileGrid(int tileZoomLevel)
- {
- int tileSize = 1 << (zoomLevel - tileZoomLevel);
- int max = (1 << tileZoomLevel) - 1;
- int x1 = grid.X / tileSize - 1;
- int x2 = (grid.X + grid.Width - 1) / tileSize + 1;
- int y1 = Math.Max(0, grid.Y / tileSize - 1);
- int y2 = Math.Min(max, (grid.Y + grid.Height - 1) / tileSize + 1);
-
- return new Int32Rect(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
+ tileImageLoader.StopDownloadTiles();
}
private void SelectTiles()
{
TileContainer tileContainer = VisualParent as TileContainer;
- int maxZoom = Math.Min(zoomLevel, MaxZoomLevel);
- int minZoom = maxZoom;
+ int maxZoomLevel = Math.Min(zoomLevel, MaxZoomLevel);
+ int minZoomLevel = maxZoomLevel;
if (tileContainer != null && tileContainer.TileLayers.IndexOf(this) == 0)
{
- minZoom = MinZoomLevel;
+ minZoomLevel = MinZoomLevel;
}
- tiles.RemoveAll(t =>
+ tiles.RemoveAll(t => t.ZoomLevel < minZoomLevel || t.ZoomLevel > maxZoomLevel);
+
+ for (int z = minZoomLevel; z <= maxZoomLevel; z++)
{
- if (t.ZoomLevel > maxZoom || t.ZoomLevel < minZoom)
+ int tileSize = 1 << (zoomLevel - z);
+ int x1 = grid.X / tileSize;
+ int x2 = (grid.X + grid.Width - 1) / tileSize;
+ int y1 = Math.Max(0, grid.Y / tileSize);
+ int y2 = Math.Min((1 << z) - 1, (grid.Y + grid.Height - 1) / tileSize);
+
+ for (int y = y1; y <= y2; y++)
{
- return true;
- }
-
- Int32Rect tileGrid = GetTileGrid(t.ZoomLevel);
- return t.X < tileGrid.X || t.X >= tileGrid.X + tileGrid.Width || t.Y < tileGrid.Y || t.Y >= tileGrid.Y + tileGrid.Height;
- });
-
- for (int tileZoomLevel = minZoom; tileZoomLevel <= maxZoom; tileZoomLevel++)
- {
- Int32Rect tileGrid = GetTileGrid(tileZoomLevel);
-
- for (int y = tileGrid.Y; y < tileGrid.Y + tileGrid.Height; y++)
- {
- for (int x = tileGrid.X; x < tileGrid.X + tileGrid.Width; x++)
+ for (int x = x1; x <= x2; x++)
{
- if (tiles.Find(t => t.ZoomLevel == tileZoomLevel && t.X == x && t.Y == y) == null)
+ if (tiles.Find(t => t.ZoomLevel == z && t.X == x && t.Y == y) == null)
{
- Tile tile = new Tile(TileSource, tileZoomLevel, x, y);
+ Tile tile = new Tile(z, x, y);
Tile equivalent = tiles.Find(t => t.Image != null && t.ZoomLevel == tile.ZoomLevel && t.XIndex == tile.XIndex && t.Y == tile.Y);
if (equivalent != null)
@@ -156,11 +144,13 @@ namespace MapControl
}
}
}
+
+ tiles.RemoveAll(t => t.ZoomLevel == z && (t.X < x1 || t.X > x2 || t.Y < y1 || t.Y > y2));
}
tiles.Sort((t1, t2) => t1.ZoomLevel - t2.ZoomLevel);
- //System.Diagnostics.Trace.TraceInformation("{0} Tiles: {1}", tiles.Count, string.Join(", ", tiles.Select(t => t.ZoomLevel.ToString())));
+ System.Diagnostics.Trace.TraceInformation("{0} Tiles: {1}", tiles.Count, string.Join(", ", tiles.Select(t => t.ZoomLevel.ToString())));
}
private void RenderTiles()