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 @@ using System.Runtime.InteropServices;
[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 @@ using System.Runtime.InteropServices;
[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 System.Threading.Tasks;
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 @@ namespace MapControl
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 @@ using System.Runtime.InteropServices;
[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 @@ namespace MapControl
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 @@ using System.Runtime.InteropServices;
[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 @@ using System.Linq;
namespace MapControl
{
+ ///
+ /// Provides helper methods for geodetic calculations on a sphere.
+ ///
public static class LocationEx
{
///
@@ -18,9 +21,48 @@ namespace MapControl
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;
- return earthRadius * Math.Acos(Math.Min(Math.Max(cosS12, -1d), 1d));
+ 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 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 @@ namespace MapControl
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 @@ using System.Threading.Tasks;
#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 @@ using Windows.Web.Http.Headers;
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))
+ if (File.Exists(path))
{
- return null;
- }
+ var file = await StorageFile.GetFileFromPathAsync(path);
- var file = await StorageFile.GetFileFromPathAsync(path);
-
- using (var stream = await file.OpenReadAsync())
- {
- var bitmapImage = new BitmapImage();
- await bitmapImage.SetSourceAsync(stream);
-
- return bitmapImage;
- }
- }
-
- 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);
+ imageSource = await CreateImageSourceAsync(stream);
}
- 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;
- }
- }
-
- return null;
}
+
+ return imageSource;
}
public static async Task LoadHttpTileImageAsync(Uri uri, Func tileCallback)
@@ -102,6 +54,21 @@ namespace MapControl
}
}
+ public static async Task 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 @@ using System.Runtime.InteropServices;
[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 System.Threading.Tasks;
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 @@ namespace MapControl
{
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 @@ namespace MapControl
{
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,67 +15,25 @@ using System.Windows.Media.Imaging;
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 = new FileStream(path, FileMode.Open, FileAccess.Read))
- {
- return (ImageSource)BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
- }
- });
- }
-
- public static async Task LoadHttpImageAsync(Uri uri, bool isTileImage)
- {
- 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 = new MemoryStream())
+ using (var stream = File.OpenRead(path))
{
- await response.Content.CopyToAsync(stream);
- stream.Seek(0, SeekOrigin.Begin);
-
- return BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
+ imageSource = CreateImageSource(stream);
}
}
- return null;
- }
+ return imageSource;
+ });
}
public static async Task LoadHttpTileImageAsync(Uri uri, Func tileCallback)
@@ -88,22 +46,46 @@ namespace MapControl
}
else if (IsTileAvailable(response.Headers))
{
- var stream = new MemoryStream();
+ using (var stream = new MemoryStream())
+ {
+ await response.Content.CopyToAsync(stream);
+ stream.Seek(0, SeekOrigin.Begin);
- await response.Content.CopyToAsync(stream);
- stream.Seek(0, SeekOrigin.Begin);
-
- await tileCallback(stream, response.Headers.CacheControl?.MaxAge);
+ await tileCallback(stream, response.Headers.CacheControl?.MaxAge);
+ }
}
return response.IsSuccessStatusCode;
}
}
+ public static ImageSource CreateImageSource(Stream stream)
+ {
+ var bitmapImage = new BitmapImage();
+ bitmapImage.BeginInit();
+ bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
+ bitmapImage.StreamSource = stream;
+ bitmapImage.EndInit();
+ bitmapImage.Freeze();
+ return bitmapImage;
+ }
+
+ public static Task CreateImageSourceAsync(Stream stream)
+ {
+ return Task.Run(() => CreateImageSource(stream));
+ }
+
+ 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 @@ namespace MapControl
{
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 @@ namespace MapControl
{
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 @@ using System.Windows;
[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.Net;
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 @@ namespace MapControl
{
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 @@ namespace MapControl
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 @@ namespace MapControl
}
}
- [TypeConverter(typeof(LocationConverter))]
- [Serializable]
- public partial class Location
- {
- }
-
public class LocationCollectionConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
@@ -40,11 +34,6 @@ namespace MapControl
}
}
- [TypeConverter(typeof(LocationCollectionConverter))]
- public partial class LocationCollection
- {
- }
-
public class BoundingBoxConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
@@ -58,12 +47,6 @@ namespace MapControl
}
}
- [TypeConverter(typeof(BoundingBoxConverter))]
- [Serializable]
- public partial class BoundingBox
- {
- }
-
public class TileSourceConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
@@ -76,9 +59,4 @@ namespace MapControl
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 @@ using System.Runtime.InteropServices;
[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 @@ namespace WpfApplication
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 @@ using System.Runtime.InteropServices;
[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