mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
Version 3.3. Improved WinRT TileImageLoader
This commit is contained in:
parent
8f5a0627fb
commit
ace1057669
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("3.2.0")]
|
||||
[assembly: AssemblyFileVersion("3.2.0")]
|
||||
[assembly: AssemblyVersion("3.3.0")]
|
||||
[assembly: AssemblyFileVersion("3.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("3.2.0")]
|
||||
[assembly: AssemblyFileVersion("3.2.0")]
|
||||
[assembly: AssemblyVersion("3.3.0")]
|
||||
[assembly: AssemblyFileVersion("3.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("3.2.0")]
|
||||
[assembly: AssemblyFileVersion("3.2.0")]
|
||||
[assembly: AssemblyVersion("3.3.0")]
|
||||
[assembly: AssemblyFileVersion("3.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("3.2.0")]
|
||||
[assembly: AssemblyFileVersion("3.2.0")]
|
||||
[assembly: AssemblyVersion("3.3.0")]
|
||||
[assembly: AssemblyFileVersion("3.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ using System.Windows.Media.Imaging;
|
|||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides the image of a map tile. ImageTileSource bypasses image
|
||||
/// downloading in TileImageLoader. By overriding the LoadImage method,
|
||||
/// an application can provide tile images from an arbitrary source.
|
||||
/// Provides the image of a map tile.
|
||||
/// ImageTileSource bypasses image downloading and optional caching in TileImageLoader.
|
||||
/// By overriding the LoadImage method, an application can provide tile images from an arbitrary source.
|
||||
/// </summary>
|
||||
public class ImageTileSource : TileSource
|
||||
{
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ namespace MapControl
|
|||
|
||||
public static readonly DependencyProperty TileSourceProperty = DependencyProperty.Register(
|
||||
nameof(TileSource), typeof(TileSource), typeof(MapTileLayer),
|
||||
new PropertyMetadata(null, (o, e) => ((MapTileLayer)o).ResetTiles()));
|
||||
new PropertyMetadata(null, (o, e) => ((MapTileLayer)o).TileSourcePropertyChanged()));
|
||||
|
||||
public static readonly DependencyProperty SourceNameProperty = DependencyProperty.Register(
|
||||
nameof(SourceName), typeof(string), typeof(MapTileLayer), new PropertyMetadata(null));
|
||||
|
|
@ -125,7 +125,7 @@ namespace MapControl
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name of the TileSource. Used as key in a TileLayerCollection and as component of a tile cache key.
|
||||
/// Name of the TileSource. Used as component of a tile cache key.
|
||||
/// </summary>
|
||||
public string SourceName
|
||||
{
|
||||
|
|
@ -134,8 +134,7 @@ namespace MapControl
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Description of the MapTileLayer.
|
||||
/// Used to display copyright information on top of the map.
|
||||
/// Description of the MapTileLayer. Used to display copyright information on top of the map.
|
||||
/// </summary>
|
||||
public string Description
|
||||
{
|
||||
|
|
@ -198,8 +197,7 @@ namespace MapControl
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optional background brush.
|
||||
/// Sets MapBase.Background if not null and the MapTileLayer is the base map layer.
|
||||
/// Optional background brush. Sets MapBase.Background if not null and the MapTileLayer is the base map layer.
|
||||
/// </summary>
|
||||
public Brush MapBackground
|
||||
{
|
||||
|
|
@ -208,8 +206,7 @@ namespace MapControl
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optional foreground brush.
|
||||
/// Sets MapBase.Foreground if not null and the MapTileLayer is the base map layer.
|
||||
/// Optional foreground brush. Sets MapBase.Foreground if not null and the MapTileLayer is the base map layer.
|
||||
/// </summary>
|
||||
public Brush MapForeground
|
||||
{
|
||||
|
|
@ -287,7 +284,16 @@ namespace MapControl
|
|||
else
|
||||
{
|
||||
TileGrid = null;
|
||||
ResetTiles();
|
||||
UpdateTiles();
|
||||
}
|
||||
}
|
||||
|
||||
private void TileSourcePropertyChanged()
|
||||
{
|
||||
if (TileGrid != null)
|
||||
{
|
||||
Tiles.Clear();
|
||||
UpdateTiles();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -295,8 +301,7 @@ namespace MapControl
|
|||
{
|
||||
if (TileGrid == null || e.ProjectionChanged || Math.Abs(e.LongitudeOffset) > 180d)
|
||||
{
|
||||
// update immediately when map projection has changed or map center has moved across 180° longitude
|
||||
UpdateTileGrid();
|
||||
UpdateTileGrid(); // update immediately when projection has changed or center has moved across 180° longitude
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -314,9 +319,8 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
private Point GetTileCenter(double tileScale)
|
||||
private Point GetTileCenter(double tileScale) // map center in tile index coordinates
|
||||
{
|
||||
// map center in tile index coordinates
|
||||
return new Point(
|
||||
tileScale * (0.5 + parentMap.Center.Longitude / 360d),
|
||||
tileScale * (0.5 - WebMercatorProjection.LatitudeToY(parentMap.Center.Latitude) / 360d));
|
||||
|
|
@ -354,27 +358,7 @@ namespace MapControl
|
|||
MatrixEx.TranslateScaleRotateTranslate(tileOrigin, scale, parentMap.Heading, viewCenter);
|
||||
}
|
||||
|
||||
private void ResetTiles()
|
||||
{
|
||||
Tiles.Clear();
|
||||
UpdateTiles();
|
||||
}
|
||||
|
||||
private void UpdateTiles()
|
||||
{
|
||||
SelectTiles();
|
||||
|
||||
Children.Clear();
|
||||
|
||||
foreach (var tile in Tiles)
|
||||
{
|
||||
Children.Add(tile.Image);
|
||||
}
|
||||
|
||||
TileImageLoader.LoadTiles(this);
|
||||
}
|
||||
|
||||
private void SelectTiles()
|
||||
{
|
||||
var newTiles = new List<Tile>();
|
||||
|
||||
|
|
@ -406,8 +390,7 @@ namespace MapControl
|
|||
|
||||
if (equivalentTile != null)
|
||||
{
|
||||
// do not animate to avoid flicker when crossing 180°
|
||||
tile.SetImage(equivalentTile.Image.Source, false);
|
||||
tile.SetImage(equivalentTile.Image.Source, false); // do not animate to avoid flicker when crossing 180° longitude
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -418,6 +401,15 @@ namespace MapControl
|
|||
}
|
||||
|
||||
Tiles = newTiles;
|
||||
|
||||
Children.Clear();
|
||||
|
||||
foreach (var tile in Tiles)
|
||||
{
|
||||
Children.Add(tile.Image);
|
||||
}
|
||||
|
||||
TileImageLoader.LoadTiles(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ using System.Windows;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("3.2.0")]
|
||||
[assembly: AssemblyFileVersion("3.2.0")]
|
||||
[assembly: AssemblyVersion("3.3.0")]
|
||||
[assembly: AssemblyFileVersion("3.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace MapControl
|
|||
/// <summary>
|
||||
/// Loads map tile images.
|
||||
/// </summary>
|
||||
internal class TileImageLoader : ITileImageLoader
|
||||
public class TileImageLoader : ITileImageLoader
|
||||
{
|
||||
public void LoadTiles(MapTileLayer tileLayer)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
|
@ -69,11 +68,11 @@ namespace MapControl
|
|||
{
|
||||
pendingTiles.Clear();
|
||||
|
||||
var tileStack = tileLayer.Tiles.Where(t => t.Pending).Reverse().ToArray();
|
||||
var tiles = tileLayer.Tiles.Where(t => t.Pending);
|
||||
|
||||
if (tileStack.Length > 0)
|
||||
if (tiles.Any())
|
||||
{
|
||||
pendingTiles.PushRange(tileStack);
|
||||
pendingTiles.PushRange(tiles.Reverse().ToArray());
|
||||
|
||||
var tileSource = tileLayer.TileSource;
|
||||
var sourceName = tileLayer.SourceName;
|
||||
|
|
|
|||
|
|
@ -64,21 +64,20 @@ namespace MapControl
|
|||
{
|
||||
pendingTiles.Clear();
|
||||
|
||||
var tiles = tileLayer.Tiles.Where(t => t.Pending);
|
||||
|
||||
if (tiles.Any())
|
||||
{
|
||||
var tileSource = tileLayer.TileSource;
|
||||
var imageTileSource = tileSource as ImageTileSource;
|
||||
var tiles = tileLayer.Tiles.Where(t => t.Pending);
|
||||
|
||||
if (imageTileSource != null)
|
||||
{
|
||||
LoadTiles(imageTileSource, tiles);
|
||||
LoadTiles(tiles, imageTileSource);
|
||||
}
|
||||
else
|
||||
{
|
||||
var tileStack = tiles.Reverse().ToArray();
|
||||
|
||||
if (tileStack.Length > 0)
|
||||
{
|
||||
pendingTiles.PushRange(tileStack);
|
||||
pendingTiles.PushRange(tiles.Reverse().ToArray());
|
||||
|
||||
var sourceName = tileLayer.SourceName;
|
||||
var maxDownloads = tileLayer.MaxParallelDownloads;
|
||||
|
|
@ -98,7 +97,7 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
private void LoadTiles(ImageTileSource tileSource, IEnumerable<Tile> tiles)
|
||||
private void LoadTiles(IEnumerable<Tile> tiles, ImageTileSource tileSource)
|
||||
{
|
||||
foreach (var tile in tiles)
|
||||
{
|
||||
|
|
@ -134,7 +133,15 @@ namespace MapControl
|
|||
|
||||
if (uri != null)
|
||||
{
|
||||
if (Cache == null || sourceName == null)
|
||||
if (!uri.IsAbsoluteUri)
|
||||
{
|
||||
await LoadImageFromFile(tile, uri.OriginalString);
|
||||
}
|
||||
else if (uri.Scheme == "file")
|
||||
{
|
||||
await LoadImageFromFile(tile, uri.LocalPath);
|
||||
}
|
||||
else if (Cache == null || sourceName == null)
|
||||
{
|
||||
await DownloadImage(tile, uri, null);
|
||||
}
|
||||
|
|
@ -186,7 +193,14 @@ namespace MapControl
|
|||
{
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
return await LoadImageFromHttpResponse(response, tile, cacheKey);
|
||||
string tileInfo;
|
||||
|
||||
if (!response.Headers.TryGetValue("X-VE-Tile-Info", out tileInfo) || tileInfo != "no-tile") // set by Bing Maps
|
||||
{
|
||||
await LoadImageFromHttpResponse(response, tile, cacheKey);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Debug.WriteLine("{0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase);
|
||||
|
|
@ -200,15 +214,8 @@ namespace MapControl
|
|||
return false;
|
||||
}
|
||||
|
||||
private async Task<bool> LoadImageFromHttpResponse(HttpResponseMessage response, Tile tile, string cacheKey)
|
||||
private async Task LoadImageFromHttpResponse(HttpResponseMessage response, Tile tile, string cacheKey)
|
||||
{
|
||||
string tileInfo;
|
||||
|
||||
if (response.Headers.TryGetValue("X-VE-Tile-Info", out tileInfo) && tileInfo == "no-tile") // set by Bing Maps
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
using (var stream = new InMemoryRandomAccessStream())
|
||||
{
|
||||
using (var content = response.Content)
|
||||
|
|
@ -219,9 +226,9 @@ namespace MapControl
|
|||
await stream.FlushAsync();
|
||||
stream.Seek(0);
|
||||
|
||||
var loaded = await LoadImageFromStream(tile, stream);
|
||||
await LoadImageFromStream(tile, stream);
|
||||
|
||||
if (loaded && cacheKey != null)
|
||||
if (cacheKey != null)
|
||||
{
|
||||
var buffer = new Windows.Storage.Streams.Buffer((uint)stream.Size);
|
||||
|
||||
|
|
@ -242,14 +249,29 @@ namespace MapControl
|
|||
|
||||
await Cache.SetAsync(cacheKey, buffer, DateTime.UtcNow.Add(expiration));
|
||||
}
|
||||
|
||||
return loaded;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> LoadImageFromStream(Tile tile, IRandomAccessStream stream)
|
||||
private async Task LoadImageFromFile(Tile tile, string path)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
try
|
||||
{
|
||||
var file = await StorageFile.GetFileFromPathAsync(path);
|
||||
|
||||
using (var stream = await file.OpenReadAsync())
|
||||
{
|
||||
await LoadImageFromStream(tile, stream);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("{0}: {1}", path, ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadImageFromStream(Tile tile, IRandomAccessStream stream)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
|
||||
await tile.Image.Dispatcher.RunAsync(CoreDispatcherPriority.Low, async () =>
|
||||
{
|
||||
|
|
@ -258,16 +280,16 @@ namespace MapControl
|
|||
var image = new BitmapImage();
|
||||
await image.SetSourceAsync(stream);
|
||||
tile.SetImage(image, true, false);
|
||||
tcs.SetResult(true);
|
||||
|
||||
tcs.SetResult(null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("{0}/{1}/{2}: {3}", tile.ZoomLevel, tile.XIndex, tile.Y, ex.Message);
|
||||
tcs.SetResult(false);
|
||||
tcs.SetException(ex);
|
||||
}
|
||||
});
|
||||
|
||||
return await tcs.Task;
|
||||
await tcs.Task;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
<DefineConstants>TRACE;DEBUG;NETFX_CORE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<GenerateLibraryLayout>true</GenerateLibraryLayout>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
<DefineConstants>TRACE;NETFX_CORE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<GenerateLibraryLayout>true</GenerateLibraryLayout>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\AzimuthalEquidistantProjection.cs">
|
||||
|
|
@ -212,7 +214,7 @@
|
|||
</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>copy "$(ProjectDir)MapControl.WinRT.xr.xml" "$(TargetDir)"</PostBuildEvent>
|
||||
<PostBuildEvent>copy "$(ProjectDir)$(TargetName).xr.xml" "$(TargetDir)$(TargetName)\"</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("3.2.0")]
|
||||
[assembly: AssemblyFileVersion("3.2.0")]
|
||||
[assembly: AssemblyVersion("3.3.0")]
|
||||
[assembly: AssemblyFileVersion("3.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("3.2.0")]
|
||||
[assembly: AssemblyFileVersion("3.2.0")]
|
||||
[assembly: AssemblyVersion("3.3.0")]
|
||||
[assembly: AssemblyFileVersion("3.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("3.2.0")]
|
||||
[assembly: AssemblyFileVersion("3.2.0")]
|
||||
[assembly: AssemblyVersion("3.3.0")]
|
||||
[assembly: AssemblyFileVersion("3.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: AssemblyVersion("3.2.0")]
|
||||
[assembly: AssemblyFileVersion("3.2.0")]
|
||||
[assembly: AssemblyVersion("3.3.0")]
|
||||
[assembly: AssemblyFileVersion("3.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("© 2017 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("3.2.0")]
|
||||
[assembly: AssemblyFileVersion("3.2.0")]
|
||||
[assembly: AssemblyVersion("3.3.0")]
|
||||
[assembly: AssemblyFileVersion("3.3.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
Loading…
Reference in a new issue