From 6a1653056f7c35b0861bf3e65aa3d18554c2863d Mon Sep 17 00:00:00 2001 From: ClemensF Date: Wed, 8 Aug 2018 23:31:52 +0200 Subject: [PATCH] Version 4.10.0: Updated target framework versions. Cleanup of TypeConverters, ImageLoader, MBTileSource. --- FileDbCache/UWP/FileDbCache.UWP.csproj | 2 +- FileDbCache/UWP/Properties/AssemblyInfo.cs | 4 +- FileDbCache/WPF/FileDbCache.WPF.csproj | 2 +- FileDbCache/WPF/Properties/AssemblyInfo.cs | 4 +- MBTiles/Shared/MBTileLayer.cs | 4 + MBTiles/UWP/MBTileSource.UWP.cs | 12 +-- MBTiles/UWP/MBTiles.UWP.csproj | 2 +- MBTiles/UWP/Properties/AssemblyInfo.cs | 4 +- MBTiles/WPF/MBTileSource.WPF.cs | 18 ++--- MBTiles/WPF/MBTiles.WPF.csproj | 10 +-- MBTiles/WPF/Properties/AssemblyInfo.cs | 4 +- MBTiles/WPF/packages.config | 2 +- MapControl/Shared/BoundingBox.cs | 5 +- MapControl/Shared/ImageLoader.cs | 69 ++++++++++++++++ MapControl/Shared/Location.cs | 5 +- MapControl/Shared/LocationCollection.cs | 5 +- MapControl/Shared/LocationEx.cs | 46 ++++++++++- MapControl/Shared/MapTileLayer.cs | 6 +- MapControl/Shared/TileSource.cs | 6 +- MapControl/UWP/ImageLoader.UWP.cs | 79 ++++++------------ MapControl/UWP/MapControl.UWP.csproj | 5 +- MapControl/UWP/Properties/AssemblyInfo.cs | 4 +- MapControl/UWP/TileImageLoader.UWP.cs | 20 ++--- MapControl/UWP/TileSource.UWP.cs | 81 ------------------- MapControl/WPF/ImageLoader.WPF.cs | 80 +++++++----------- MapControl/WPF/MapControl.WPF.csproj | 10 ++- MapControl/WPF/MapGraticule.WPF.cs | 4 +- MapControl/WPF/Properties/AssemblyInfo.cs | 4 +- MapControl/WPF/TileImageLoader.WPF.cs | 17 ++-- MapControl/WPF/TypeConverters.WPF.cs | 22 ----- .../UniversalApp/Properties/AssemblyInfo.cs | 4 +- SampleApps/UniversalApp/UniversalApp.csproj | 2 +- SampleApps/WpfApplication/App.config | 2 +- SampleApps/WpfApplication/OutlinedText.cs | 2 +- .../WpfApplication/Properties/AssemblyInfo.cs | 4 +- .../WpfApplication/WpfApplication.csproj | 2 +- 36 files changed, 266 insertions(+), 286 deletions(-) create mode 100644 MapControl/Shared/ImageLoader.cs delete mode 100644 MapControl/UWP/TileSource.UWP.cs diff --git a/FileDbCache/UWP/FileDbCache.UWP.csproj b/FileDbCache/UWP/FileDbCache.UWP.csproj index 5377b144..0b2e47c7 100644 --- a/FileDbCache/UWP/FileDbCache.UWP.csproj +++ b/FileDbCache/UWP/FileDbCache.UWP.csproj @@ -46,7 +46,7 @@ - 6.1.5 + 6.1.7 diff --git a/FileDbCache/UWP/Properties/AssemblyInfo.cs b/FileDbCache/UWP/Properties/AssemblyInfo.cs index 1a9df272..96088024 100644 --- a/FileDbCache/UWP/Properties/AssemblyInfo.cs +++ b/FileDbCache/UWP/Properties/AssemblyInfo.cs @@ -7,8 +7,8 @@ [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2018 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("4.9.0")] -[assembly: AssemblyFileVersion("4.9.0")] +[assembly: AssemblyVersion("4.10.0")] +[assembly: AssemblyFileVersion("4.10.0")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/FileDbCache/WPF/FileDbCache.WPF.csproj b/FileDbCache/WPF/FileDbCache.WPF.csproj index 27254a1b..c97e9b99 100644 --- a/FileDbCache/WPF/FileDbCache.WPF.csproj +++ b/FileDbCache/WPF/FileDbCache.WPF.csproj @@ -9,7 +9,7 @@ Properties MapControl.Caching FileDbCache.WPF - v4.5 + v4.7.2 512 diff --git a/FileDbCache/WPF/Properties/AssemblyInfo.cs b/FileDbCache/WPF/Properties/AssemblyInfo.cs index 1f8636b3..6c7b6e99 100644 --- a/FileDbCache/WPF/Properties/AssemblyInfo.cs +++ b/FileDbCache/WPF/Properties/AssemblyInfo.cs @@ -7,8 +7,8 @@ [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2018 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("4.9.0")] -[assembly: AssemblyFileVersion("4.9.0")] +[assembly: AssemblyVersion("4.10.0")] +[assembly: AssemblyFileVersion("4.10.0")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/MBTiles/Shared/MBTileLayer.cs b/MBTiles/Shared/MBTileLayer.cs index 133f2315..dda0a76b 100644 --- a/MBTiles/Shared/MBTileLayer.cs +++ b/MBTiles/Shared/MBTileLayer.cs @@ -1,3 +1,7 @@ +// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control +// © 2018 Clemens Fischer +// Licensed under the Microsoft Public License (Ms-PL) + #if WINDOWS_UWP using Windows.UI.Xaml; #else diff --git a/MBTiles/UWP/MBTileSource.UWP.cs b/MBTiles/UWP/MBTileSource.UWP.cs index 700c3102..564b3afe 100644 --- a/MBTiles/UWP/MBTileSource.UWP.cs +++ b/MBTiles/UWP/MBTileSource.UWP.cs @@ -1,4 +1,8 @@ -using System; +// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control +// © 2018 Clemens Fischer +// Licensed under the Microsoft Public License (Ms-PL) + +using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices.WindowsRuntime; @@ -6,7 +10,6 @@ using Microsoft.Data.Sqlite; using Windows.Storage.Streams; using Windows.UI.Xaml.Media; -using Windows.UI.Xaml.Media.Imaging; namespace MapControl { @@ -53,10 +56,7 @@ public override async Task LoadImageAsync(int x, int y, int zoomLev await stream.WriteAsync(buffer.AsBuffer()); stream.Seek(0); - var bitmapImage = new BitmapImage(); - await bitmapImage.SetSourceAsync(stream); - - imageSource = bitmapImage; + imageSource = await ImageLoader.CreateImageSourceAsync(stream); } } } diff --git a/MBTiles/UWP/MBTiles.UWP.csproj b/MBTiles/UWP/MBTiles.UWP.csproj index c46f7d57..de35813a 100644 --- a/MBTiles/UWP/MBTiles.UWP.csproj +++ b/MBTiles/UWP/MBTiles.UWP.csproj @@ -52,7 +52,7 @@ 2.1.0 - 6.1.5 + 6.1.7 diff --git a/MBTiles/UWP/Properties/AssemblyInfo.cs b/MBTiles/UWP/Properties/AssemblyInfo.cs index 1c77eafd..1c89b963 100644 --- a/MBTiles/UWP/Properties/AssemblyInfo.cs +++ b/MBTiles/UWP/Properties/AssemblyInfo.cs @@ -7,8 +7,8 @@ [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2018 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("4.9.0")] -[assembly: AssemblyFileVersion("4.9.0")] +[assembly: AssemblyVersion("4.10.0")] +[assembly: AssemblyFileVersion("4.10.0")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/MBTiles/WPF/MBTileSource.WPF.cs b/MBTiles/WPF/MBTileSource.WPF.cs index 67853e4b..a018a1a9 100644 --- a/MBTiles/WPF/MBTileSource.WPF.cs +++ b/MBTiles/WPF/MBTileSource.WPF.cs @@ -1,11 +1,14 @@ -using System; +// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control +// © 2018 Clemens Fischer +// Licensed under the Microsoft Public License (Ms-PL) + +using System; using System.Collections.Generic; +using System.Data.SQLite; using System.Diagnostics; using System.IO; using System.Threading.Tasks; -using System.Data.SQLite; using System.Windows.Media; -using System.Windows.Media.Imaging; namespace MapControl { @@ -47,13 +50,10 @@ public override async Task LoadImageAsync(int x, int y, int zoomLev if (buffer != null) { - imageSource = await Task.Run(() => + using (var stream = new MemoryStream(buffer)) { - using (var stream = new MemoryStream(buffer)) - { - return BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); - } - }); + imageSource = await ImageLoader.CreateImageSourceAsync(stream); + } } } } diff --git a/MBTiles/WPF/MBTiles.WPF.csproj b/MBTiles/WPF/MBTiles.WPF.csproj index c800fd89..97c33c7f 100644 --- a/MBTiles/WPF/MBTiles.WPF.csproj +++ b/MBTiles/WPF/MBTiles.WPF.csproj @@ -9,7 +9,7 @@ Properties MapControl MBTiles.WPF - v4.5 + v4.7.2 512 @@ -38,8 +38,8 @@ - - ..\..\packages\System.Data.SQLite.Core.1.0.107.0\lib\net45\System.Data.SQLite.dll + + ..\..\packages\System.Data.SQLite.Core.1.0.108.0\lib\net46\System.Data.SQLite.dll @@ -61,11 +61,11 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + \ No newline at end of file diff --git a/MBTiles/WPF/Properties/AssemblyInfo.cs b/MBTiles/WPF/Properties/AssemblyInfo.cs index e91869a0..3b788678 100644 --- a/MBTiles/WPF/Properties/AssemblyInfo.cs +++ b/MBTiles/WPF/Properties/AssemblyInfo.cs @@ -7,8 +7,8 @@ [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2018 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("4.9.0")] -[assembly: AssemblyFileVersion("4.9.0")] +[assembly: AssemblyVersion("4.10.0")] +[assembly: AssemblyFileVersion("4.10.0")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/MBTiles/WPF/packages.config b/MBTiles/WPF/packages.config index a1feb583..7d999d46 100644 --- a/MBTiles/WPF/packages.config +++ b/MBTiles/WPF/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/MapControl/Shared/BoundingBox.cs b/MapControl/Shared/BoundingBox.cs index 810dc34d..927fcf62 100644 --- a/MapControl/Shared/BoundingBox.cs +++ b/MapControl/Shared/BoundingBox.cs @@ -10,7 +10,10 @@ namespace MapControl /// /// A geographic bounding box with south and north latitude and west and east longitude values in degrees. /// - public partial class BoundingBox +#if !WINDOWS_UWP + [System.ComponentModel.TypeConverter(typeof(BoundingBoxConverter))] +#endif + public class BoundingBox { private double south; private double west; diff --git a/MapControl/Shared/ImageLoader.cs b/MapControl/Shared/ImageLoader.cs new file mode 100644 index 00000000..4dccbb31 --- /dev/null +++ b/MapControl/Shared/ImageLoader.cs @@ -0,0 +1,69 @@ +// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control +// © 2018 Clemens Fischer +// Licensed under the Microsoft Public License (Ms-PL) + +using System; +using System.Diagnostics; +using System.Threading.Tasks; +#if WINDOWS_UWP +using Windows.Web.Http; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Media.Imaging; +#else +using System.Net.Http; +using System.Windows.Media; +using System.Windows.Media.Imaging; +#endif + +namespace MapControl +{ + public static partial class ImageLoader + { + /// + /// The HttpClient instance used when image data is downloaded from a web resource. + /// + public static HttpClient HttpClient { get; set; } = new HttpClient(); + + public static async Task LoadImageAsync(Uri uri, bool isTileImage) + { + ImageSource imageSource = null; + + if (!uri.IsAbsoluteUri || uri.Scheme == "file") + { + imageSource = await LoadLocalImageAsync(uri); + } + else if (uri.Scheme == "http") + { + imageSource = await LoadHttpImageAsync(uri, isTileImage); + } + else + { + imageSource = new BitmapImage(uri); + } + + return imageSource; + } + + public static async Task LoadHttpImageAsync(Uri uri, bool isTileImage) + { + ImageSource imageSource = null; + + using (var response = await HttpClient.GetAsync(uri)) + { + if (!response.IsSuccessStatusCode) + { + Debug.WriteLine("ImageLoader: {0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase); + } + else if (!isTileImage || IsTileAvailable(response.Headers)) + { + using (var stream = await GetResponseStreamAsync(response.Content)) + { + imageSource = await CreateImageSourceAsync(stream); + } + } + + return imageSource; + } + } + } +} \ No newline at end of file diff --git a/MapControl/Shared/Location.cs b/MapControl/Shared/Location.cs index eeba9eb0..91e1c43b 100644 --- a/MapControl/Shared/Location.cs +++ b/MapControl/Shared/Location.cs @@ -10,7 +10,10 @@ namespace MapControl /// /// A geographic location with latitude and longitude values in degrees. /// - public partial class Location : IEquatable +#if !WINDOWS_UWP + [System.ComponentModel.TypeConverter(typeof(LocationConverter))] +#endif + public class Location : IEquatable { private double latitude; private double longitude; diff --git a/MapControl/Shared/LocationCollection.cs b/MapControl/Shared/LocationCollection.cs index 43d3ec86..2cd4b147 100644 --- a/MapControl/Shared/LocationCollection.cs +++ b/MapControl/Shared/LocationCollection.cs @@ -11,7 +11,10 @@ namespace MapControl /// /// A collection of Locations with support for parsing. /// - public partial class LocationCollection : List +#if !WINDOWS_UWP + [System.ComponentModel.TypeConverter(typeof(LocationCollectionConverter))] +#endif + public class LocationCollection : List { public LocationCollection() { diff --git a/MapControl/Shared/LocationEx.cs b/MapControl/Shared/LocationEx.cs index f340728d..d555a83f 100644 --- a/MapControl/Shared/LocationEx.cs +++ b/MapControl/Shared/LocationEx.cs @@ -7,6 +7,9 @@ namespace MapControl { + /// + /// Provides helper methods for geodetic calculations on a sphere. + /// public static class LocationEx { /// @@ -18,9 +21,48 @@ public static double GreatCircleDistance(this Location location1, Location locat var lon1 = location1.Longitude * Math.PI / 180d; var lat2 = location2.Latitude * Math.PI / 180d; var lon2 = location2.Longitude * Math.PI / 180d; - var cosS12 = Math.Sin(lat1) * Math.Sin(lat2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Cos(lon2 - lon1); + var sinLat1 = Math.Sin(lat1); + var cosLat1 = Math.Cos(lat1); + var sinLat2 = Math.Sin(lat2); + var cosLat2 = Math.Cos(lat2); + var cosLon12 = Math.Cos(lon2 - lon1); + var cosS12 = sinLat1 * sinLat2 + cosLat1 * cosLat2 * cosLon12; + var s12 = 0d; + + if (Math.Abs(cosS12) < 0.99999999) + { + s12 = Math.Acos(Math.Min(Math.Max(cosS12, -1d), 1d)); + } + else + { + var sinLon12 = Math.Sin(lon2 - lon1); + var a = cosLat1 * sinLat2 - sinLat1 * cosLat2 * cosLon12; + var b = cosLat2 * sinLon12; + s12 = Math.Atan2(Math.Sqrt(a * a + b * b), cosS12); + } + + return earthRadius * s12; + } + + /// + /// see https://en.wikipedia.org/wiki/Great-circle_navigation + /// + public static Location GreatCircleLocation(this Location location, double azimuth, double distance, double earthRadius = MapProjection.Wgs84EquatorialRadius) + { + var s12 = distance / earthRadius; + var az1 = azimuth * Math.PI / 180d; + var lat1 = location.Latitude * Math.PI / 180d; + var lon1 = location.Longitude * Math.PI / 180d; + var sinS12 = Math.Sin(s12); + var cosS12 = Math.Cos(s12); + var sinAz1 = Math.Sin(az1); + var cosAz1 = Math.Cos(az1); + var sinLat1 = Math.Sin(lat1); + var cosLat1 = Math.Cos(lat1); + var lat2 = Math.Asin(sinLat1 * cosS12 + cosLat1 * sinS12 * cosAz1); + var lon2 = lon1 + Math.Atan2(sinS12 * sinAz1, (cosLat1 * cosS12 - sinLat1 * sinS12 * cosAz1)); - return earthRadius * Math.Acos(Math.Min(Math.Max(cosS12, -1d), 1d)); + return new Location(lat2 / Math.PI * 180d, lon2 / Math.PI * 180d); } public static LocationCollection CalculateMeridianLocations(this Location location, double latitude2, double resolution = 1d) diff --git a/MapControl/Shared/MapTileLayer.cs b/MapControl/Shared/MapTileLayer.cs index 2f5e880b..d9ca85a2 100644 --- a/MapControl/Shared/MapTileLayer.cs +++ b/MapControl/Shared/MapTileLayer.cs @@ -344,9 +344,11 @@ private void UpdateTiles() var maxZoomLevel = Math.Min(TileGrid.ZoomLevel, MaxZoomLevel); var minZoomLevel = MinZoomLevel; - if (minZoomLevel < maxZoomLevel && parentMap.MapLayer != this) // load lower tiles only in a base layer + if (minZoomLevel < maxZoomLevel && + parentMap.MapLayer != this && + parentMap.Children.Cast().FirstOrDefault() != this) { - minZoomLevel = maxZoomLevel; + minZoomLevel = maxZoomLevel; // do not load lower level tiles if this is note a "base" layer } for (var z = minZoomLevel; z <= maxZoomLevel; z++) diff --git a/MapControl/Shared/TileSource.cs b/MapControl/Shared/TileSource.cs index cdac0647..b516105b 100644 --- a/MapControl/Shared/TileSource.cs +++ b/MapControl/Shared/TileSource.cs @@ -9,6 +9,7 @@ #if WINDOWS_UWP using Windows.UI.Xaml.Media; #else +using System.ComponentModel; using System.Windows.Media; #endif @@ -17,7 +18,10 @@ namespace MapControl /// /// Provides the download Uri or ImageSource of map tiles. /// - public partial class TileSource +#if !WINDOWS_UWP + [TypeConverter(typeof(TileSourceConverter))] +#endif + public class TileSource { private Func getUri; private string uriFormat; diff --git a/MapControl/UWP/ImageLoader.UWP.cs b/MapControl/UWP/ImageLoader.UWP.cs index a602cd37..bd563dec 100644 --- a/MapControl/UWP/ImageLoader.UWP.cs +++ b/MapControl/UWP/ImageLoader.UWP.cs @@ -15,72 +15,24 @@ namespace MapControl { - public static class ImageLoader + public static partial class ImageLoader { - /// - /// The HttpClient instance used when image data is downloaded from a web resource. - /// - public static HttpClient HttpClient { get; set; } = new HttpClient(); - - public static async Task LoadImageAsync(Uri uri, bool isTileImage) - { - if (!uri.IsAbsoluteUri || uri.Scheme == "file") - { - return await LoadLocalImageAsync(uri); - } - - if (uri.Scheme == "http") - { - return await LoadHttpImageAsync(uri, isTileImage); - } - - return new BitmapImage(uri); - } - public static async Task LoadLocalImageAsync(Uri uri) { + ImageSource imageSource = null; var path = uri.IsAbsoluteUri ? uri.LocalPath : uri.OriginalString; - if (!File.Exists(path)) - { - return null; - } - - var file = await StorageFile.GetFileFromPathAsync(path); - - using (var stream = await file.OpenReadAsync()) + if (File.Exists(path)) { - var bitmapImage = new BitmapImage(); - await bitmapImage.SetSourceAsync(stream); - - return bitmapImage; - } - } + var file = await StorageFile.GetFileFromPathAsync(path); - public static async Task LoadHttpImageAsync(Uri uri, bool isTileImage) - { - using (var response = await HttpClient.GetAsync(uri)) - { - if (!response.IsSuccessStatusCode) + using (var stream = await file.OpenReadAsync()) { - Debug.WriteLine("ImageLoader: {0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase); - } - else if (!isTileImage || IsTileAvailable(response.Headers)) - { - using (var stream = new InMemoryRandomAccessStream()) - { - await response.Content.WriteToStreamAsync(stream); - stream.Seek(0); - - var bitmapImage = new BitmapImage(); - await bitmapImage.SetSourceAsync(stream); - - return bitmapImage; - } + imageSource = await CreateImageSourceAsync(stream); } - - return null; } + + return imageSource; } public static async Task LoadHttpTileImageAsync(Uri uri, Func tileCallback) @@ -102,6 +54,21 @@ public static async Task LoadHttpTileImageAsync(Uri uri, Func CreateImageSourceAsync(IRandomAccessStream stream) + { + var bitmapImage = new BitmapImage(); + await bitmapImage.SetSourceAsync(stream); + return bitmapImage; + } + + private static async Task GetResponseStreamAsync(IHttpContent content) + { + var stream = new InMemoryRandomAccessStream(); + await content.WriteToStreamAsync(stream); + stream.Seek(0); + return stream; + } + private static bool IsTileAvailable(HttpResponseHeaderCollection responseHeaders) { return !responseHeaders.TryGetValue("X-VE-Tile-Info", out string tileInfo) || tileInfo != "no-tile"; diff --git a/MapControl/UWP/MapControl.UWP.csproj b/MapControl/UWP/MapControl.UWP.csproj index 2416e8f1..e5abf127 100644 --- a/MapControl/UWP/MapControl.UWP.csproj +++ b/MapControl/UWP/MapControl.UWP.csproj @@ -67,6 +67,9 @@ HyperlinkText.cs + + ImageLoader.cs + Intersections.cs @@ -168,7 +171,7 @@ - 6.1.5 + 6.1.7 diff --git a/MapControl/UWP/Properties/AssemblyInfo.cs b/MapControl/UWP/Properties/AssemblyInfo.cs index a8d38dd1..d766e2da 100644 --- a/MapControl/UWP/Properties/AssemblyInfo.cs +++ b/MapControl/UWP/Properties/AssemblyInfo.cs @@ -7,8 +7,8 @@ [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2018 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("4.9.0")] -[assembly: AssemblyFileVersion("4.9.0")] +[assembly: AssemblyVersion("4.10.0")] +[assembly: AssemblyFileVersion("4.10.0")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/MapControl/UWP/TileImageLoader.UWP.cs b/MapControl/UWP/TileImageLoader.UWP.cs index 335832ed..e2136a96 100644 --- a/MapControl/UWP/TileImageLoader.UWP.cs +++ b/MapControl/UWP/TileImageLoader.UWP.cs @@ -8,11 +8,10 @@ using Windows.Storage; using Windows.Storage.Streams; using Windows.UI.Core; -using Windows.UI.Xaml.Media.Imaging; namespace MapControl { - public partial class TileImageLoader : ITileImageLoader + public partial class TileImageLoader { /// /// Default StorageFolder where an IImageCache instance may save cached data, @@ -43,12 +42,12 @@ private async Task LoadTileImageAsync(Tile tile, Uri uri, string cacheKey) { try { - loaded = await ImageLoader.LoadHttpTileImageAsync(uri, async (buffer, maxAge) => - { - await SetTileImageAsync(tile, buffer); // create BitmapImage before caching - - await Cache.SetAsync(cacheKey, buffer, GetExpiration(maxAge)); - }); + loaded = await ImageLoader.LoadHttpTileImageAsync(uri, + async (buffer, maxAge) => + { + await SetTileImageAsync(tile, buffer); // create BitmapImage before caching + await Cache.SetAsync(cacheKey, buffer, GetExpiration(maxAge)); + }); } catch (Exception ex) { @@ -76,10 +75,7 @@ private async Task SetTileImageAsync(Tile tile, IBuffer buffer) { try { - var bitmapImage = new BitmapImage(); - await bitmapImage.SetSourceAsync(stream); - - tile.SetImage(bitmapImage); + tile.SetImage(await ImageLoader.CreateImageSourceAsync(stream)); tcs.SetResult(null); } catch (Exception ex) diff --git a/MapControl/UWP/TileSource.UWP.cs b/MapControl/UWP/TileSource.UWP.cs deleted file mode 100644 index 3110d51f..00000000 --- a/MapControl/UWP/TileSource.UWP.cs +++ /dev/null @@ -1,81 +0,0 @@ -// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control -// © 2018 Clemens Fischer -// Licensed under the Microsoft Public License (Ms-PL) - -using System; -using System.Diagnostics; -using System.IO; -using System.Threading.Tasks; -using Windows.Storage; -using Windows.Storage.Streams; -using Windows.UI.Xaml.Media; -using Windows.UI.Xaml.Media.Imaging; -using Windows.Web.Http; -using Windows.Web.Http.Headers; - -namespace MapControl -{ - public partial class TileSource - { - /// - /// The HttpClient instance used when image data is downloaded from a web resource. - /// - public static HttpClient HttpClient { get; set; } = new HttpClient(); - - /// - /// Check HTTP response headers for tile availability, e.g. X-VE-Tile-Info=no-tile - /// - public static bool IsTileAvailable(HttpResponseHeaderCollection responseHeaders) - { - string tileInfo; - - return !responseHeaders.TryGetValue("X-VE-Tile-Info", out tileInfo) || tileInfo != "no-tile"; - } - - protected static async Task LoadLocalImageAsync(Uri uri) - { - var path = uri.IsAbsoluteUri ? uri.LocalPath : uri.OriginalString; - - if (!await Task.Run(() => File.Exists(path))) - { - return null; - } - - var file = await StorageFile.GetFileFromPathAsync(path); - - using (var stream = await file.OpenReadAsync()) - { - var bitmapImage = new BitmapImage(); - await bitmapImage.SetSourceAsync(stream); - - return bitmapImage; - } - } - - protected static async Task LoadHttpImageAsync(Uri uri) - { - using (var response = await HttpClient.GetAsync(uri)) - { - if (!response.IsSuccessStatusCode) - { - Debug.WriteLine("TileSource: {0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase); - } - else if (IsTileAvailable(response.Headers)) - { - using (var stream = new InMemoryRandomAccessStream()) - { - await response.Content.WriteToStreamAsync(stream); - stream.Seek(0); - - var bitmapImage = new BitmapImage(); - await bitmapImage.SetSourceAsync(stream); - - return bitmapImage; - } - } - } - - return null; - } - } -} diff --git a/MapControl/WPF/ImageLoader.WPF.cs b/MapControl/WPF/ImageLoader.WPF.cs index 5ffdbb14..cceee79c 100644 --- a/MapControl/WPF/ImageLoader.WPF.cs +++ b/MapControl/WPF/ImageLoader.WPF.cs @@ -15,47 +15,28 @@ namespace MapControl { - public static class ImageLoader + public static partial class ImageLoader { - /// - /// The HttpClient instance used when image data is downloaded from a web resource. - /// - public static HttpClient HttpClient { get; set; } = new HttpClient(); - - public static async Task LoadImageAsync(Uri uri, bool isTileImage) - { - if (!uri.IsAbsoluteUri || uri.Scheme == "file") - { - return await LoadLocalImageAsync(uri); - } - - if (uri.Scheme == "http") - { - return await LoadHttpImageAsync(uri, isTileImage); - } - - return new BitmapImage(uri); - } - public static Task LoadLocalImageAsync(Uri uri) { return Task.Run(() => { + ImageSource imageSource = null; var path = uri.IsAbsoluteUri ? uri.LocalPath : uri.OriginalString; - if (!File.Exists(path)) + if (File.Exists(path)) { - return null; + using (var stream = File.OpenRead(path)) + { + imageSource = CreateImageSource(stream); + } } - using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read)) - { - return (ImageSource)BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); - } + return imageSource; }); } - public static async Task LoadHttpImageAsync(Uri uri, bool isTileImage) + public static async Task LoadHttpTileImageAsync(Uri uri, Func tileCallback) { using (var response = await HttpClient.GetAsync(uri)) { @@ -63,47 +44,48 @@ public static async Task LoadHttpImageAsync(Uri uri, bool isTileIma { Debug.WriteLine("ImageLoader: {0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase); } - else if (!isTileImage || IsTileAvailable(response.Headers)) + else if (IsTileAvailable(response.Headers)) { using (var stream = new MemoryStream()) { await response.Content.CopyToAsync(stream); stream.Seek(0, SeekOrigin.Begin); - return BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); + await tileCallback(stream, response.Headers.CacheControl?.MaxAge); } } - return null; + return response.IsSuccessStatusCode; } } - public static async Task LoadHttpTileImageAsync(Uri uri, Func tileCallback) + public static ImageSource CreateImageSource(Stream stream) { - using (var response = await HttpClient.GetAsync(uri)) - { - if (!response.IsSuccessStatusCode) - { - Debug.WriteLine("ImageLoader: {0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase); - } - else if (IsTileAvailable(response.Headers)) - { - var stream = new MemoryStream(); - - await response.Content.CopyToAsync(stream); - stream.Seek(0, SeekOrigin.Begin); + var bitmapImage = new BitmapImage(); + bitmapImage.BeginInit(); + bitmapImage.CacheOption = BitmapCacheOption.OnLoad; + bitmapImage.StreamSource = stream; + bitmapImage.EndInit(); + bitmapImage.Freeze(); + return bitmapImage; + } - await tileCallback(stream, response.Headers.CacheControl?.MaxAge); - } + public static Task CreateImageSourceAsync(Stream stream) + { + return Task.Run(() => CreateImageSource(stream)); + } - return response.IsSuccessStatusCode; - } + private static async Task GetResponseStreamAsync(HttpContent content) + { + var stream = new MemoryStream(); + await content.CopyToAsync(stream); + stream.Seek(0, SeekOrigin.Begin); + return stream; } private static bool IsTileAvailable(HttpResponseHeaders responseHeaders) { IEnumerable tileInfo; - return !responseHeaders.TryGetValues("X-VE-Tile-Info", out tileInfo) || !tileInfo.Contains("no-tile"); } } diff --git a/MapControl/WPF/MapControl.WPF.csproj b/MapControl/WPF/MapControl.WPF.csproj index 8bf4be89..9c7b4b58 100644 --- a/MapControl/WPF/MapControl.WPF.csproj +++ b/MapControl/WPF/MapControl.WPF.csproj @@ -9,11 +9,12 @@ Properties MapControl MapControl.WPF - v4.5 + v4.7.2 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 - + + true @@ -25,6 +26,7 @@ 4 + false none @@ -33,6 +35,7 @@ TRACE prompt 4 + false true @@ -86,6 +89,9 @@ HyperlinkText.cs + + ImageLoader.cs + Intersections.cs diff --git a/MapControl/WPF/MapGraticule.WPF.cs b/MapControl/WPF/MapGraticule.WPF.cs index 1bb02a85..3bacb560 100644 --- a/MapControl/WPF/MapGraticule.WPF.cs +++ b/MapControl/WPF/MapGraticule.WPF.cs @@ -72,7 +72,7 @@ private void DrawCylindricalGraticule(DrawingContext drawingContext, MapProjecti { latLabels.Add(new Label(lat, new FormattedText( GetLabelText(lat, labelFormat, "NS"), - CultureInfo.InvariantCulture, FlowDirection.LeftToRight, typeface, FontSize, Foreground))); + CultureInfo.InvariantCulture, FlowDirection.LeftToRight, typeface, FontSize, Foreground, 1d))); drawingContext.DrawLine(pen, projection.LocationToViewportPoint(new Location(lat, boundingBox.West)), @@ -83,7 +83,7 @@ private void DrawCylindricalGraticule(DrawingContext drawingContext, MapProjecti { lonLabels.Add(new Label(lon, new FormattedText( GetLabelText(Location.NormalizeLongitude(lon), labelFormat, "EW"), - CultureInfo.InvariantCulture, FlowDirection.LeftToRight, typeface, FontSize, Foreground))); + CultureInfo.InvariantCulture, FlowDirection.LeftToRight, typeface, FontSize, Foreground, 1d))); drawingContext.DrawLine(pen, projection.LocationToViewportPoint(new Location(boundingBox.South, lon)), diff --git a/MapControl/WPF/Properties/AssemblyInfo.cs b/MapControl/WPF/Properties/AssemblyInfo.cs index 3d5e72bc..fdd1007a 100644 --- a/MapControl/WPF/Properties/AssemblyInfo.cs +++ b/MapControl/WPF/Properties/AssemblyInfo.cs @@ -8,8 +8,8 @@ [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2018 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("4.9.0")] -[assembly: AssemblyFileVersion("4.9.0")] +[assembly: AssemblyVersion("4.10.0")] +[assembly: AssemblyFileVersion("4.10.0")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/MapControl/WPF/TileImageLoader.WPF.cs b/MapControl/WPF/TileImageLoader.WPF.cs index ab6973a6..08fd41db 100644 --- a/MapControl/WPF/TileImageLoader.WPF.cs +++ b/MapControl/WPF/TileImageLoader.WPF.cs @@ -9,11 +9,10 @@ using System.Runtime.Caching; using System.Text; using System.Threading.Tasks; -using System.Windows.Media.Imaging; namespace MapControl { - public partial class TileImageLoader : ITileImageLoader + public partial class TileImageLoader { /// /// Default folder path where an ObjectCache instance may save cached data, @@ -44,12 +43,12 @@ private async Task LoadTileImageAsync(Tile tile, Uri uri, string cacheKey) { try { - loaded = await ImageLoader.LoadHttpTileImageAsync(uri, async (stream, maxAge) => - { - await SetTileImageAsync(tile, stream); // create BitmapFrame before caching - - SetCachedImage(cacheKey, stream, GetExpiration(maxAge)); - }); + loaded = await ImageLoader.LoadHttpTileImageAsync(uri, + async (stream, maxAge) => + { + await SetTileImageAsync(tile, stream); // create BitmapImage before caching + SetCachedImage(cacheKey, stream, GetExpiration(maxAge)); + }); } catch (Exception ex) { @@ -68,7 +67,7 @@ private async Task LoadTileImageAsync(Tile tile, Uri uri, string cacheKey) private async Task SetTileImageAsync(Tile tile, MemoryStream stream) { - var imageSource = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); + var imageSource = ImageLoader.CreateImageSource(stream); await tile.Image.Dispatcher.InvokeAsync(() => tile.SetImage(imageSource)); } diff --git a/MapControl/WPF/TypeConverters.WPF.cs b/MapControl/WPF/TypeConverters.WPF.cs index 99684021..a5b03fa3 100644 --- a/MapControl/WPF/TypeConverters.WPF.cs +++ b/MapControl/WPF/TypeConverters.WPF.cs @@ -21,12 +21,6 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c } } - [TypeConverter(typeof(LocationConverter))] - [Serializable] - public partial class Location - { - } - public class LocationCollectionConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) @@ -40,11 +34,6 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c } } - [TypeConverter(typeof(LocationCollectionConverter))] - public partial class LocationCollection - { - } - public class BoundingBoxConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) @@ -58,12 +47,6 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c } } - [TypeConverter(typeof(BoundingBoxConverter))] - [Serializable] - public partial class BoundingBox - { - } - public class TileSourceConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) @@ -76,9 +59,4 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c return new TileSource { UriFormat = value as string }; } } - - [TypeConverter(typeof(TileSourceConverter))] - public partial class TileSource - { - } } diff --git a/SampleApps/UniversalApp/Properties/AssemblyInfo.cs b/SampleApps/UniversalApp/Properties/AssemblyInfo.cs index 4ce24073..134f1bbd 100644 --- a/SampleApps/UniversalApp/Properties/AssemblyInfo.cs +++ b/SampleApps/UniversalApp/Properties/AssemblyInfo.cs @@ -8,7 +8,7 @@ [assembly: AssemblyCopyright("© 2018 Clemens Fischer")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("4.9.0")] -[assembly: AssemblyFileVersion("4.9.0")] +[assembly: AssemblyVersion("4.10.0")] +[assembly: AssemblyFileVersion("4.10.0")] [assembly: AssemblyConfiguration("")] [assembly: ComVisible(false)] diff --git a/SampleApps/UniversalApp/UniversalApp.csproj b/SampleApps/UniversalApp/UniversalApp.csproj index a95d24c2..ed29b57b 100644 --- a/SampleApps/UniversalApp/UniversalApp.csproj +++ b/SampleApps/UniversalApp/UniversalApp.csproj @@ -156,7 +156,7 @@ - 6.1.5 + 6.1.7 diff --git a/SampleApps/WpfApplication/App.config b/SampleApps/WpfApplication/App.config index f1c3c49e..7c73fc9d 100644 --- a/SampleApps/WpfApplication/App.config +++ b/SampleApps/WpfApplication/App.config @@ -1,6 +1,6 @@ - + diff --git a/SampleApps/WpfApplication/OutlinedText.cs b/SampleApps/WpfApplication/OutlinedText.cs index ae5ee879..4b2b748c 100644 --- a/SampleApps/WpfApplication/OutlinedText.cs +++ b/SampleApps/WpfApplication/OutlinedText.cs @@ -134,7 +134,7 @@ private bool CheckGlyphRun() advanceWidths[i] = glyphTypeface.AdvanceWidths[glyphIndex] * FontSize; } - glyphRun = new GlyphRun(glyphTypeface, 0, false, FontSize, glyphIndices, new Point(), advanceWidths, null, null, null, null, null, null); + glyphRun = new GlyphRun(glyphTypeface, 0, false, FontSize, 1f, glyphIndices, new Point(), advanceWidths, null, null, null, null, null, null); outline = glyphRun.BuildGeometry().GetWidenedPathGeometry(new Pen(null, OutlineThickness * 2d)); } diff --git a/SampleApps/WpfApplication/Properties/AssemblyInfo.cs b/SampleApps/WpfApplication/Properties/AssemblyInfo.cs index 48448dfa..86185f97 100644 --- a/SampleApps/WpfApplication/Properties/AssemblyInfo.cs +++ b/SampleApps/WpfApplication/Properties/AssemblyInfo.cs @@ -7,8 +7,8 @@ [assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCopyright("© 2018 Clemens Fischer")] [assembly: AssemblyTrademark("")] -[assembly: AssemblyVersion("4.9.0")] -[assembly: AssemblyFileVersion("4.9.0")] +[assembly: AssemblyVersion("4.10.0")] +[assembly: AssemblyFileVersion("4.10.0")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] diff --git a/SampleApps/WpfApplication/WpfApplication.csproj b/SampleApps/WpfApplication/WpfApplication.csproj index 1d0fa813..e3601a3c 100644 --- a/SampleApps/WpfApplication/WpfApplication.csproj +++ b/SampleApps/WpfApplication/WpfApplication.csproj @@ -9,7 +9,7 @@ Properties WpfApplication WpfApplication - v4.5 + v4.7.2 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4