diff --git a/MBTiles/Shared/MBTileData.cs b/MBTiles/Shared/MBTileData.cs index 68f3b7b7..c079345a 100644 --- a/MBTiles/Shared/MBTileData.cs +++ b/MBTiles/Shared/MBTileData.cs @@ -25,9 +25,19 @@ namespace MapControl.MBTiles connection = new SQLiteConnection("Data Source=" + Path.GetFullPath(file)); } - public Task OpenAsync() + public async Task OpenAsync() { - return connection.OpenAsync(); + await connection.OpenAsync(); + + using (var command = new SQLiteCommand("create table if not exists metadata (name string, value string)", connection)) + { + await command.ExecuteNonQueryAsync(); + } + + using (var command = new SQLiteCommand("create table if not exists tiles (zoom_level integer, tile_column integer, tile_row integer, tile_data blob)", connection)) + { + await command.ExecuteNonQueryAsync(); + } } public void Close() @@ -68,11 +78,6 @@ namespace MapControl.MBTiles { try { - using (var command = new SQLiteCommand("create table if not exists metadata (name string, value string)", connection)) - { - await command.ExecuteNonQueryAsync(); - } - using (var command = new SQLiteCommand("insert or replace into metadata (name, value) values (@n, @v)", connection)) { foreach (var keyValue in metadata) @@ -117,11 +122,6 @@ namespace MapControl.MBTiles { try { - using (var command = new SQLiteCommand("create table if not exists tiles (zoom_level integer, tile_column integer, tile_row integer, tile_data blob)", connection)) - { - await command.ExecuteNonQueryAsync(); - } - using (var command = new SQLiteCommand("insert or replace into tiles (zoom_level, tile_column, tile_row, tile_data) values (@z, @x, @y, @b)", connection)) { command.Parameters.AddWithValue("@z", zoomLevel); diff --git a/MBTiles/Shared/MBTileLayer.cs b/MBTiles/Shared/MBTileLayer.cs index 8684bb41..d21819d8 100644 --- a/MBTiles/Shared/MBTileLayer.cs +++ b/MBTiles/Shared/MBTileLayer.cs @@ -11,6 +11,9 @@ using System.Windows; namespace MapControl.MBTiles { + /// + /// MapTileLayer that uses an MBTiles SQLite Database. See https://wiki.openstreetmap.org/wiki/MBTiles. + /// public class MBTileLayer : MapTileLayer { public static readonly DependencyProperty FileProperty = DependencyProperty.Register( diff --git a/MBTiles/Shared/MBTileSource.cs b/MBTiles/Shared/MBTileSource.cs index 8ebd8795..5db7d4a7 100644 --- a/MBTiles/Shared/MBTileSource.cs +++ b/MBTiles/Shared/MBTileSource.cs @@ -16,48 +16,47 @@ namespace MapControl.MBTiles { private readonly MBTileData tileData; - public string Name { get; private set; } - public string Description { get; private set; } - public int? MinZoom { get; private set; } - public int? MaxZoom { get; private set; } - public MBTileSource(string file) { tileData = new MBTileData(file); } + public string Name { get; private set; } + public string Description { get; private set; } + public int? MinZoom { get; private set; } + public int? MaxZoom { get; private set; } + public async Task Initialize() { await tileData.OpenAsync(); var metadata = await tileData.ReadMetadataAsync(); - string name; - string description; - string minzoom; - string maxzoom; + string s; int minZoom; int maxZoom; - if (metadata.TryGetValue("name", out name)) - { - Name = name; - } + Name = (metadata.TryGetValue("name", out s)) ? s : null; - if (metadata.TryGetValue("description", out description)) - { - Description = description; - } + Description = (metadata.TryGetValue("description", out s)) ? s : null; - if (metadata.TryGetValue("minzoom", out minzoom) && int.TryParse(minzoom, out minZoom)) + if (metadata.TryGetValue("minzoom", out s) && int.TryParse(s, out minZoom)) { MinZoom = minZoom; } + else + { + MinZoom = null; + } - if (metadata.TryGetValue("maxzoom", out maxzoom) && int.TryParse(maxzoom, out maxZoom)) + if (metadata.TryGetValue("maxzoom", out s) && int.TryParse(s, out maxZoom)) { MaxZoom = maxZoom; } + else + { + MaxZoom = null; + } } public void Dispose() diff --git a/MBTiles/WPF/MBTiles.WPF.csproj b/MBTiles/WPF/MBTiles.WPF.csproj index 1f463e55..72ed69c5 100644 --- a/MBTiles/WPF/MBTiles.WPF.csproj +++ b/MBTiles/WPF/MBTiles.WPF.csproj @@ -47,7 +47,6 @@ ..\..\packages\System.Data.SQLite.Core.1.0.111.0\lib\net46\System.Data.SQLite.dll - diff --git a/MapImages/Shared/GroundOverlayPanel.cs b/MapImages/Shared/GroundOverlayPanel.cs index 5dd7e2a1..1305f879 100644 --- a/MapImages/Shared/GroundOverlayPanel.cs +++ b/MapImages/Shared/GroundOverlayPanel.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; +using System.IO.Compression; using System.Linq; using System.Threading.Tasks; using System.Xml; @@ -22,7 +23,7 @@ using System.Windows.Media; namespace MapControl.Images { - public partial class GroundOverlayPanel : MapPanel + public class GroundOverlayPanel : MapPanel { class LatLonBox : BoundingBox { @@ -99,7 +100,8 @@ namespace MapControl.Images FrameworkElement overlay = new Image { Source = imageOverlay.ImageSource, - Stretch = Stretch.Fill + Stretch = Stretch.Fill, + UseLayoutRounding = false }; if (imageOverlay.LatLonBox.Rotation != 0d) @@ -108,7 +110,7 @@ namespace MapControl.Images overlay.RenderTransformOrigin = new Point(0.5, 0.5); // additional Panel for map rotation, see MapPanel.ArrangeElementWithBoundingBox - var panel = new Grid { Background = null }; + var panel = new Grid { UseLayoutRounding = false }; panel.Children.Add(overlay); overlay = panel; } @@ -119,6 +121,71 @@ namespace MapControl.Images } } + private static async Task> ReadGroundOverlaysFromArchiveAsync(string archiveFile) + { + using (var archive = await Task.Run(() => ZipFile.OpenRead(archiveFile))) + { + var docEntry = await Task.Run(() => archive.GetEntry("doc.kml") ?? archive.Entries.FirstOrDefault(e => e.Name.EndsWith(".kml"))); + + if (docEntry == null) + { + throw new ArgumentException("No KML entry found in " + archiveFile); + } + + var imageOverlays = await Task.Run(() => + { + var kmlDocument = new XmlDocument(); + + using (var docStream = docEntry.Open()) + { + kmlDocument.Load(docStream); + } + + return ReadGroundOverlays(kmlDocument).ToList(); + }); + + foreach (var imageOverlay in imageOverlays) + { + var imageEntry = await Task.Run(() => archive.GetEntry(imageOverlay.ImagePath)); + + if (imageEntry != null) + { + using (var zipStream = imageEntry.Open()) + using (var memoryStream = new MemoryStream()) + { + await zipStream.CopyToAsync(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + + imageOverlay.ImageSource = await ImageLoader.LoadImageAsync(memoryStream); + } + } + } + + return imageOverlays; + } + } + + private static async Task> ReadGroundOverlaysFromFileAsync(string docFile) + { + docFile = Path.GetFullPath(docFile); + var docUri = new Uri(docFile); + + var imageOverlays = await Task.Run(() => + { + var kmlDocument = new XmlDocument(); + kmlDocument.Load(docFile); + + return ReadGroundOverlays(kmlDocument).ToList(); + }); + + foreach (var imageOverlay in imageOverlays) + { + imageOverlay.ImageSource = await ImageLoader.LoadImageAsync(new Uri(docUri, imageOverlay.ImagePath)); + } + + return imageOverlays; + } + private static IEnumerable ReadGroundOverlays(XmlDocument kmlDocument) { foreach (XmlElement groundOverlayElement in kmlDocument.GetElementsByTagName("GroundOverlay")) diff --git a/MapImages/UWP/GroundOverlayPanel.UWP.cs b/MapImages/UWP/GroundOverlayPanel.UWP.cs deleted file mode 100644 index 732c2a3c..00000000 --- a/MapImages/UWP/GroundOverlayPanel.UWP.cs +++ /dev/null @@ -1,88 +0,0 @@ -// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control -// © 2019 Clemens Fischer -// Licensed under the Microsoft Public License (Ms-PL) - -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Threading.Tasks; -using System.Xml; -using Windows.Storage; - -namespace MapControl.Images -{ - public partial class GroundOverlayPanel - { - public GroundOverlayPanel() - { - UseLayoutRounding = false; - } - - private static async Task> ReadGroundOverlaysFromFileAsync(string docFile) - { - docFile = Path.GetFullPath(docFile); - - var file = await StorageFile.GetFileFromPathAsync(docFile); - var kmlDocument = new XmlDocument(); - - using (var stream = await file.OpenReadAsync()) - { - kmlDocument.Load(stream.AsStreamForRead()); - } - - var imageOverlays = await Task.Run(() => ReadGroundOverlays(kmlDocument).ToList()); - var docUri = new Uri(docFile); - - foreach (var imageOverlay in imageOverlays) - { - imageOverlay.ImageSource = await ImageLoader.LoadImageAsync(new Uri(docUri, imageOverlay.ImagePath)); - } - - return imageOverlays; - } - - private static async Task> ReadGroundOverlaysFromArchiveAsync(string archiveFile) - { - using (var archive = ZipFile.OpenRead(archiveFile)) - { - var docEntry = archive.GetEntry("doc.kml") - ?? archive.Entries.FirstOrDefault(e => e.Name.EndsWith(".kml")); - - if (docEntry == null) - { - throw new ArgumentException("No KML entry found in " + archiveFile); - } - - var kmlDocument = new XmlDocument(); - - using (var docStream = docEntry.Open()) - { - kmlDocument.Load(docStream); - } - - var imageOverlays = await Task.Run(() => ReadGroundOverlays(kmlDocument).ToList()); - - foreach (var imageOverlay in imageOverlays) - { - var imageEntry = archive.GetEntry(imageOverlay.ImagePath); - - if (imageEntry != null) - { - using (var zipStream = imageEntry.Open()) - using (var memoryStream = new MemoryStream()) - { - await zipStream.CopyToAsync(memoryStream); - memoryStream.Seek(0, SeekOrigin.Begin); - - imageOverlay.ImageSource = await ImageLoader.LoadImageAsync(memoryStream); - } - } - } - - return imageOverlays; - } - } - } -} diff --git a/MapImages/UWP/MapImages.UWP.csproj b/MapImages/UWP/MapImages.UWP.csproj index b7655cd1..f1d2065b 100644 --- a/MapImages/UWP/MapImages.UWP.csproj +++ b/MapImages/UWP/MapImages.UWP.csproj @@ -49,7 +49,6 @@ ZoomLevelToOpacityConverter.cs - diff --git a/MapImages/WPF/GroundOverlayPanel.WPF.cs b/MapImages/WPF/GroundOverlayPanel.WPF.cs deleted file mode 100644 index 8004b93b..00000000 --- a/MapImages/WPF/GroundOverlayPanel.WPF.cs +++ /dev/null @@ -1,83 +0,0 @@ -// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control -// © 2019 Clemens Fischer -// Licensed under the Microsoft Public License (Ms-PL) - -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Threading.Tasks; -using System.Xml; - -namespace MapControl.Images -{ - public partial class GroundOverlayPanel - { - private static Task> ReadGroundOverlaysFromFileAsync(string docFile) - { - return Task.Run(() => - { - docFile = Path.GetFullPath(docFile); - - var kmlDocument = new XmlDocument(); - kmlDocument.Load(docFile); - - var imageOverlays = ReadGroundOverlays(kmlDocument).ToList(); - var docDir = Path.GetDirectoryName(docFile); - - foreach (var imageOverlay in imageOverlays) - { - imageOverlay.ImageSource = ImageLoader.LoadImage(Path.Combine(docDir, imageOverlay.ImagePath)); - } - - return imageOverlays; - }); - } - - private static Task> ReadGroundOverlaysFromArchiveAsync(string archiveFile) - { - return Task.Run(() => - { - using (var archive = ZipFile.OpenRead(archiveFile)) - { - var docEntry = archive.GetEntry("doc.kml") - ?? archive.Entries.FirstOrDefault(e => e.Name.EndsWith(".kml")); - - if (docEntry == null) - { - throw new ArgumentException("No KML entry found in " + archiveFile); - } - - var kmlDocument = new XmlDocument(); - - using (var docStream = docEntry.Open()) - { - kmlDocument.Load(docStream); - } - - var imageOverlays = ReadGroundOverlays(kmlDocument).ToList(); - - foreach (var imageOverlay in imageOverlays) - { - var imageEntry = archive.GetEntry(imageOverlay.ImagePath); - - if (imageEntry != null) - { - using (var zipStream = imageEntry.Open()) - using (var memoryStream = new MemoryStream()) - { - zipStream.CopyTo(memoryStream); - memoryStream.Seek(0, SeekOrigin.Begin); - - imageOverlay.ImageSource = ImageLoader.LoadImage(memoryStream); - } - } - } - - return imageOverlays; - } - }); - } - } -} diff --git a/MapImages/WPF/MapImages.WPF.csproj b/MapImages/WPF/MapImages.WPF.csproj index 3996f7ec..53b99bfe 100644 --- a/MapImages/WPF/MapImages.WPF.csproj +++ b/MapImages/WPF/MapImages.WPF.csproj @@ -57,7 +57,6 @@ ZoomLevelToOpacityConverter.cs -