From 65c20c76b249a94051df9907497835ffe95d619b Mon Sep 17 00:00:00 2001 From: ClemensFischer Date: Wed, 3 Dec 2025 08:21:15 +0100 Subject: [PATCH] WmtsTileMatrixSet --- MapControl/Shared/MapTileLayer.cs | 24 +++++++------- MapControl/Shared/WmtsCapabilities.cs | 8 ----- MapControl/Shared/WmtsTileMatrix.cs | 3 +- MapControl/Shared/WmtsTileMatrixSet.cs | 43 +++++++++++++++++++++++++ MapControl/WPF/BitmapTileMatrixLayer.cs | 19 ++++++----- 5 files changed, 67 insertions(+), 30 deletions(-) create mode 100644 MapControl/Shared/WmtsTileMatrixSet.cs diff --git a/MapControl/Shared/MapTileLayer.cs b/MapControl/Shared/MapTileLayer.cs index 04677e9f..0023d8b1 100644 --- a/MapControl/Shared/MapTileLayer.cs +++ b/MapControl/Shared/MapTileLayer.cs @@ -24,9 +24,9 @@ namespace MapControl /// public class MapTileLayer : TilePyramidLayer { - private const int TileSize = 256; + private const int tileSize = 256; - private static readonly Point MapTopLeft = new(-180d * MapProjection.Wgs84MeterPerDegree, + private static readonly Point mapTopLeft = new(-180d * MapProjection.Wgs84MeterPerDegree, 180d * MapProjection.Wgs84MeterPerDegree); public static readonly DependencyProperty TileSourceProperty = @@ -116,9 +116,9 @@ namespace MapControl { // Arrange tiles relative to TileMatrix.XMin/YMin. // - var tileSize = TileSize << (TileMatrix.ZoomLevel - tile.ZoomLevel); - var x = tileSize * tile.X - TileSize * TileMatrix.XMin; - var y = tileSize * tile.Y - TileSize * TileMatrix.YMin; + var tileSize = MapTileLayer.tileSize << (TileMatrix.ZoomLevel - tile.ZoomLevel); + var x = tileSize * tile.X - MapTileLayer.tileSize * TileMatrix.XMin; + var y = tileSize * tile.Y - MapTileLayer.tileSize * TileMatrix.YMin; tile.Image.Width = tileSize; tile.Image.Height = tileSize; @@ -134,11 +134,11 @@ namespace MapControl { // Tile matrix origin in pixels. // - var tileMatrixOrigin = new Point(TileSize * TileMatrix.XMin, TileSize * TileMatrix.YMin); + var tileMatrixOrigin = new Point(tileSize * TileMatrix.XMin, tileSize * TileMatrix.YMin); var tileMatrixScale = MapBase.ZoomLevelToScale(TileMatrix.ZoomLevel); ((MatrixTransform)RenderTransform).Matrix = - ParentMap.ViewTransform.GetTileLayerTransform(tileMatrixScale, MapTopLeft, tileMatrixOrigin); + ParentMap.ViewTransform.GetTileLayerTransform(tileMatrixScale, mapTopLeft, tileMatrixOrigin); } } @@ -178,14 +178,14 @@ namespace MapControl // Tile matrix bounds in pixels. // - var bounds = ParentMap.ViewTransform.GetTileMatrixBounds(tileMatrixScale, MapTopLeft, ParentMap.ActualWidth, ParentMap.ActualHeight); + var bounds = ParentMap.ViewTransform.GetTileMatrixBounds(tileMatrixScale, mapTopLeft, ParentMap.ActualWidth, ParentMap.ActualHeight); // Tile X and Y bounds. // - var xMin = (int)Math.Floor(bounds.X / TileSize); - var yMin = (int)Math.Floor(bounds.Y / TileSize); - var xMax = (int)Math.Floor((bounds.X + bounds.Width) / TileSize); - var yMax = (int)Math.Floor((bounds.Y + bounds.Height) / TileSize); + var xMin = (int)Math.Floor(bounds.X / tileSize); + var yMin = (int)Math.Floor(bounds.Y / tileSize); + var xMax = (int)Math.Floor((bounds.X + bounds.Width) / tileSize); + var yMax = (int)Math.Floor((bounds.Y + bounds.Height) / tileSize); if (TileMatrix != null && TileMatrix.ZoomLevel == tileMatrixZoomLevel && diff --git a/MapControl/Shared/WmtsCapabilities.cs b/MapControl/Shared/WmtsCapabilities.cs index 11b3e09f..206d764a 100644 --- a/MapControl/Shared/WmtsCapabilities.cs +++ b/MapControl/Shared/WmtsCapabilities.cs @@ -13,14 +13,6 @@ using Avalonia; namespace MapControl { - public class WmtsTileMatrixSet(string identifier, string supportedCrsId, string uriTemplate, IEnumerable tileMatrixes) - { - public string Identifier => identifier; - public string SupportedCrsId => supportedCrsId; - public string UriTemplate { get; } = uriTemplate.Replace("{TileMatrixSet}", identifier); - public List TileMatrixes { get; } = tileMatrixes.OrderBy(m => m.Scale).ToList(); - } - /// /// For reference see https://www.ogc.org/standards/wmts, 07-057r7_Web_Map_Tile_Service_Standard.pdf /// diff --git a/MapControl/Shared/WmtsTileMatrix.cs b/MapControl/Shared/WmtsTileMatrix.cs index 7f242a0b..17631149 100644 --- a/MapControl/Shared/WmtsTileMatrix.cs +++ b/MapControl/Shared/WmtsTileMatrix.cs @@ -8,8 +8,7 @@ using Avalonia; namespace MapControl { public class WmtsTileMatrix( - string identifier, double scale, Point topLeft, - int tileWidth, int tileHeight, int matrixWidth, int matrixHeight) + string identifier, double scale, Point topLeft, int tileWidth, int tileHeight, int matrixWidth, int matrixHeight) { public string Identifier => identifier; public double Scale => scale; diff --git a/MapControl/Shared/WmtsTileMatrixSet.cs b/MapControl/Shared/WmtsTileMatrixSet.cs new file mode 100644 index 00000000..255e51dd --- /dev/null +++ b/MapControl/Shared/WmtsTileMatrixSet.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.Linq; +#if WPF +using System.Windows; +#elif AVALONIA +using Avalonia; +#endif + +namespace MapControl +{ + public class WmtsTileMatrixSet( + string identifier, string supportedCrsId, string uriTemplate, IEnumerable tileMatrixes) + { + public string Identifier => identifier; + public string SupportedCrsId => supportedCrsId; + public string UriTemplate { get; } = uriTemplate.Replace("{TileMatrixSet}", identifier); + public List TileMatrixes { get; } = tileMatrixes.OrderBy(m => m.Scale).ToList(); + + public static WmtsTileMatrixSet CreateOpenStreetMapTileMatrixSet( + string uriTemplate, int minZoomLevel = 0, int maxZoomLevel = 19) + { + const int tileSize = 256; + const double baseScale = tileSize / (360d * MapProjection.Wgs84MeterPerDegree); + + Point mapTopLeft = new(-180d * MapProjection.Wgs84MeterPerDegree, + 180d * MapProjection.Wgs84MeterPerDegree); + + return new WmtsTileMatrixSet(null, + WebMercatorProjection.DefaultCrsId, + uriTemplate + .Replace("{z}", "{0}") + .Replace("{x}", "{1}") + .Replace("{y}", "{2}"), + Enumerable + .Range(minZoomLevel, maxZoomLevel - minZoomLevel + 1) + .Select(z => (z, 1 << z)) + .Select(t => new WmtsTileMatrix( + t.zoomLevel.ToString(), + t.matrixSize * baseScale, mapTopLeft, + tileSize, tileSize, t.matrixSize, t.matrixSize))); + } + } +} diff --git a/MapControl/WPF/BitmapTileMatrixLayer.cs b/MapControl/WPF/BitmapTileMatrixLayer.cs index 7a40228f..4f4ef754 100644 --- a/MapControl/WPF/BitmapTileMatrixLayer.cs +++ b/MapControl/WPF/BitmapTileMatrixLayer.cs @@ -28,9 +28,9 @@ namespace MapControl PixelBuffer = new byte[4 * width * height]; bitmap.CopyPixels(PixelBuffer, 4 * width, 0); - - Completed?.Invoke(this, EventArgs.Empty); } + + Completed?.Invoke(this, EventArgs.Empty); } } @@ -172,14 +172,17 @@ namespace MapControl tile.Completed -= OnTileCompleted; - Dispatcher.Invoke(() => + if (tile.PixelBuffer != null) { - if (tile.X >= TileMatrix.XMin && tile.X <= TileMatrix.XMax && - tile.Y >= TileMatrix.YMin && tile.Y <= TileMatrix.YMax) + Dispatcher.Invoke(() => { - CopyTile(tile); - } - }); + if (tile.X >= TileMatrix.XMin && tile.X <= TileMatrix.XMax && + tile.Y >= TileMatrix.YMin && tile.Y <= TileMatrix.YMax) + { + CopyTile(tile); + } + }); + } } } }