mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
Fixed flicker when map center moves across the date line.
This commit is contained in:
parent
02b9cb4354
commit
1d5703d382
|
|
@ -458,11 +458,6 @@ namespace MapControl
|
|||
UpdateTransform();
|
||||
}
|
||||
|
||||
protected override void OnRender(DrawingContext drawingContext)
|
||||
{
|
||||
drawingContext.DrawRectangle(Background, null, new Rect(RenderSize));
|
||||
}
|
||||
|
||||
protected override void OnViewportChanged()
|
||||
{
|
||||
base.OnViewportChanged();
|
||||
|
|
|
|||
|
|
@ -36,14 +36,17 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
public ImageSource Image
|
||||
public ImageSource Source
|
||||
{
|
||||
get { return Brush.ImageSource; }
|
||||
set
|
||||
set { Brush.ImageSource = value; }
|
||||
}
|
||||
|
||||
public void SetSource(ImageSource source)
|
||||
{
|
||||
if (Brush.ImageSource == null)
|
||||
if (Source == null)
|
||||
{
|
||||
BitmapImage bitmap = value as BitmapImage;
|
||||
BitmapImage bitmap = source as BitmapImage;
|
||||
|
||||
if (bitmap != null && bitmap.IsDownloading)
|
||||
{
|
||||
|
|
@ -56,8 +59,7 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
Brush.ImageSource = value;
|
||||
}
|
||||
Source = source;
|
||||
}
|
||||
|
||||
private void BitmapDownloadCompleted(object sender, EventArgs e)
|
||||
|
|
@ -71,7 +73,7 @@ namespace MapControl
|
|||
{
|
||||
((BitmapImage)sender).DownloadCompleted -= BitmapDownloadCompleted;
|
||||
((BitmapImage)sender).DownloadFailed -= BitmapDownloadFailed;
|
||||
Brush.ImageSource = null;
|
||||
Source = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ namespace MapControl
|
|||
|
||||
public void AddTileLayers(int index, IEnumerable<TileLayer> tileLayers)
|
||||
{
|
||||
Matrix transform = GetVisualTransform();
|
||||
Matrix tileLayerTransform = GetTileLayerTransform();
|
||||
|
||||
foreach (TileLayer tileLayer in tileLayers)
|
||||
{
|
||||
|
|
@ -43,7 +43,7 @@ namespace MapControl
|
|||
}
|
||||
|
||||
Children.Insert(index++, tileLayer);
|
||||
tileLayer.TransformMatrix = transform;
|
||||
tileLayer.TransformMatrix = tileLayerTransform;
|
||||
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
|
||||
}
|
||||
}
|
||||
|
|
@ -72,13 +72,20 @@ namespace MapControl
|
|||
}
|
||||
|
||||
public double SetViewportTransform(double mapZoomLevel, double mapRotation, Point mapOrigin, Point viewportOrigin, Size viewportSize)
|
||||
{
|
||||
double scale = Math.Pow(2d, zoomLevel) * 256d / 360d;
|
||||
double oldMapOriginX = (origin.X - offset.X) / scale - 180d;
|
||||
|
||||
if (zoomLevel != mapZoomLevel)
|
||||
{
|
||||
zoomLevel = mapZoomLevel;
|
||||
scale = Math.Pow(2d, zoomLevel) * 256d / 360d;
|
||||
}
|
||||
|
||||
rotation = mapRotation;
|
||||
size = viewportSize;
|
||||
origin = viewportOrigin;
|
||||
|
||||
double scale = Math.Pow(2d, zoomLevel) * 256d / 360d;
|
||||
offset.X = origin.X - (180d + mapOrigin.X) * scale;
|
||||
offset.Y = origin.Y - (180d - mapOrigin.Y) * scale;
|
||||
|
||||
|
|
@ -88,19 +95,27 @@ namespace MapControl
|
|||
transform.RotateAt(rotation, origin.X, origin.Y);
|
||||
ViewportTransform.Matrix = transform;
|
||||
|
||||
transform = GetVisualTransform();
|
||||
Matrix tileLayerTransform = GetTileLayerTransform();
|
||||
|
||||
foreach (TileLayer tileLayer in Children)
|
||||
{
|
||||
tileLayer.TransformMatrix = transform;
|
||||
tileLayer.TransformMatrix = tileLayerTransform;
|
||||
}
|
||||
|
||||
if (Math.Sign(mapOrigin.X) == Math.Sign(oldMapOriginX))
|
||||
{
|
||||
updateTimer.IsEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// immediately handle map origin leap when map center moves across the date line
|
||||
UpdateTiles(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
private Matrix GetVisualTransform()
|
||||
private Matrix GetTileLayerTransform()
|
||||
{
|
||||
// Calculates the transform matrix that enables rendering of 256x256 tile rectangles in
|
||||
// TileLayer.UpdateTiles with origin at tileGrid.X and tileGrid.Y to minimize rounding errors.
|
||||
|
|
@ -148,11 +163,11 @@ namespace MapControl
|
|||
{
|
||||
tileZoomLevel = zoom;
|
||||
tileGrid = grid;
|
||||
transform = GetVisualTransform();
|
||||
Matrix tileLayerTransform = GetTileLayerTransform();
|
||||
|
||||
foreach (TileLayer tileLayer in Children)
|
||||
{
|
||||
tileLayer.TransformMatrix = transform;
|
||||
tileLayer.TransformMatrix = tileLayerTransform;
|
||||
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,9 +70,9 @@ namespace MapControl
|
|||
this.tileLayer = tileLayer;
|
||||
}
|
||||
|
||||
internal void BeginGetTiles(ICollection<Tile> tiles)
|
||||
internal void BeginGetTiles(IEnumerable<Tile> tiles)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(BeginGetTilesAsync, new List<Tile>(tiles.Where(t => t.Image == null && t.Uri == null)));
|
||||
ThreadPool.QueueUserWorkItem(BeginGetTilesAsync, new List<Tile>(tiles.Where(t => t.Source == null && t.Uri == null)));
|
||||
}
|
||||
|
||||
internal void CancelGetTiles()
|
||||
|
|
@ -89,23 +89,26 @@ namespace MapControl
|
|||
{
|
||||
ImageTileSource imageTileSource = (ImageTileSource)tileLayer.TileSource;
|
||||
|
||||
newTiles.ForEach(tile =>
|
||||
foreach (Tile tile in newTiles)
|
||||
{
|
||||
tileLayer.Dispatcher.BeginInvoke(DispatcherPriority.Background,
|
||||
(Action)(() => tile.Image = imageTileSource.GetImage(tile.XIndex, tile.Y, tile.ZoomLevel)));
|
||||
});
|
||||
(Action)(() => tile.SetSource(imageTileSource.GetImage(tile.XIndex, tile.Y, tile.ZoomLevel))));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Cache == null)
|
||||
{
|
||||
newTiles.ForEach(tile => pendingTiles.Enqueue(tile));
|
||||
foreach (Tile tile in newTiles)
|
||||
{
|
||||
pendingTiles.Enqueue(tile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Tile> outdatedTiles = new List<Tile>(newTiles.Count);
|
||||
|
||||
newTiles.ForEach(tile =>
|
||||
foreach (Tile tile in newTiles)
|
||||
{
|
||||
string key = CacheKey(tile);
|
||||
byte[] buffer = Cache.Get(key) as byte[];
|
||||
|
|
@ -125,9 +128,12 @@ namespace MapControl
|
|||
// update cached image
|
||||
outdatedTiles.Add(tile);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
outdatedTiles.ForEach(tile => pendingTiles.Enqueue(tile));
|
||||
foreach (Tile tile in outdatedTiles)
|
||||
{
|
||||
pendingTiles.Enqueue(tile);
|
||||
}
|
||||
}
|
||||
|
||||
while (downloadThreadCount < Math.Min(pendingTiles.Count, tileLayer.MaxParallelDownloads))
|
||||
|
|
@ -182,7 +188,7 @@ namespace MapControl
|
|||
return false;
|
||||
}
|
||||
|
||||
tileLayer.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)(() => tile.Image = bitmap));
|
||||
tileLayer.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)(() => tile.SetSource(bitmap)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace MapControl
|
|||
public class TileLayer : DrawingVisual
|
||||
{
|
||||
private readonly TileImageLoader tileImageLoader;
|
||||
private readonly List<Tile> tiles = new List<Tile>();
|
||||
private List<Tile> tiles = new List<Tile>();
|
||||
private string description = string.Empty;
|
||||
private Int32Rect grid;
|
||||
private int zoomLevel;
|
||||
|
|
@ -25,8 +25,8 @@ namespace MapControl
|
|||
public TileLayer()
|
||||
{
|
||||
tileImageLoader = new TileImageLoader(this);
|
||||
VisualEdgeMode = EdgeMode.Aliased;
|
||||
VisualTransform = new MatrixTransform();
|
||||
VisualEdgeMode = EdgeMode.Aliased;
|
||||
MinZoomLevel = 1;
|
||||
MaxZoomLevel = 18;
|
||||
MaxParallelDownloads = 8;
|
||||
|
|
@ -62,15 +62,15 @@ namespace MapControl
|
|||
{
|
||||
SelectTiles();
|
||||
RenderTiles();
|
||||
|
||||
tileImageLoader.BeginGetTiles(tiles);
|
||||
}
|
||||
}
|
||||
|
||||
internal void ClearTiles()
|
||||
{
|
||||
tiles.Clear();
|
||||
tileImageLoader.CancelGetTiles();
|
||||
tiles.Clear();
|
||||
RenderTiles();
|
||||
}
|
||||
|
||||
private void SelectTiles()
|
||||
|
|
@ -84,7 +84,7 @@ namespace MapControl
|
|||
minZoomLevel = MinZoomLevel;
|
||||
}
|
||||
|
||||
tiles.RemoveAll(t => t.ZoomLevel < minZoomLevel || t.ZoomLevel > maxZoomLevel);
|
||||
List<Tile> newTiles = new List<Tile>();
|
||||
|
||||
for (int z = minZoomLevel; z <= maxZoomLevel; z++)
|
||||
{
|
||||
|
|
@ -98,35 +98,33 @@ namespace MapControl
|
|||
{
|
||||
for (int x = x1; x <= x2; x++)
|
||||
{
|
||||
if (tiles.Find(t => t.ZoomLevel == z && t.X == x && t.Y == y) == null)
|
||||
Tile tile = tiles.Find(t => t.ZoomLevel == z && t.X == x && t.Y == y);
|
||||
|
||||
if (tile == null)
|
||||
{
|
||||
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);
|
||||
tile = new Tile(z, x, y);
|
||||
Tile equivalent = tiles.Find(t => t.Source != null && t.ZoomLevel == z && t.XIndex == tile.XIndex && t.Y == y);
|
||||
|
||||
if (equivalent != null)
|
||||
{
|
||||
tile.Image = equivalent.Image;
|
||||
tile.Source = equivalent.Source;
|
||||
}
|
||||
}
|
||||
|
||||
tiles.Add(tile);
|
||||
newTiles.Add(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(", ", System.Linq.Enumerable.Select(tiles, t => t.ZoomLevel.ToString())));
|
||||
tiles = newTiles;
|
||||
//System.Diagnostics.Trace.TraceInformation("{0} Tiles: {1}", tiles.Count, string.Join(", ", tiles.Select(t => t.ZoomLevel.ToString())));
|
||||
}
|
||||
|
||||
private void RenderTiles()
|
||||
{
|
||||
using (DrawingContext drawingContext = RenderOpen())
|
||||
{
|
||||
tiles.ForEach(tile =>
|
||||
foreach (Tile tile in tiles)
|
||||
{
|
||||
int tileSize = 256 << (zoomLevel - tile.ZoomLevel);
|
||||
Rect tileRect = new Rect(tileSize * tile.X - 256 * grid.X, tileSize * tile.Y - 256 * grid.Y, tileSize, tileSize);
|
||||
|
|
@ -136,7 +134,7 @@ namespace MapControl
|
|||
//if (tile.ZoomLevel == zoomLevel)
|
||||
// drawingContext.DrawText(new FormattedText(string.Format("{0}-{1}-{2}", tile.ZoomLevel, tile.X, tile.Y),
|
||||
// System.Globalization.CultureInfo.InvariantCulture, FlowDirection.LeftToRight, new Typeface("Segoe UI"), 14, Brushes.Black), tileRect.TopLeft);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue