Compare commits

...

2 commits

Author SHA1 Message Date
ClemensFischer 286926e1ea Moved TileSource property to MapTileLayer 2025-11-28 23:22:10 +01:00
ClemensFischer 733c3d1266 Updated WmtsTileLayer 2025-11-28 21:59:25 +01:00
4 changed files with 96 additions and 75 deletions

View file

@ -29,6 +29,10 @@ namespace MapControl
private static readonly Point MapTopLeft = new(-180d * MapProjection.Wgs84MeterPerDegree,
180d * MapProjection.Wgs84MeterPerDegree);
public static readonly DependencyProperty TileSourceProperty =
DependencyPropertyHelper.Register<MapTileLayer, TileSource>(nameof(TileSource), null,
(layer, oldValue, newValue) => layer.UpdateTileCollection(true));
public static readonly DependencyProperty MinZoomLevelProperty =
DependencyPropertyHelper.Register<MapTileLayer, int>(nameof(MinZoomLevel), 0);
@ -59,6 +63,15 @@ namespace MapControl
public ICollection<ImageTile> Tiles { get; private set; } = [];
/// <summary>
/// Provides the ImagesSource or image request Uri for map tiles.
/// </summary>
public TileSource TileSource
{
get => (TileSource)GetValue(TileSourceProperty);
set => SetValue(TileSourceProperty, value);
}
/// <summary>
/// Minimum zoom level supported by the MapTileLayer. Default value is 0.
/// </summary>
@ -129,26 +142,36 @@ namespace MapControl
}
}
protected override void UpdateTileCollection(bool reset)
protected override void UpdateTileCollection()
{
if (ParentMap == null || !SupportedCrsIds.Contains(ParentMap.MapProjection.CrsId))
UpdateTileCollection(false);
}
private void UpdateTileCollection(bool tileSourceChanged)
{
if (TileSource == null || ParentMap == null || !SupportedCrsIds.Contains(ParentMap.MapProjection.CrsId))
{
CancelLoadTiles();
Children.Clear();
Tiles.Clear();
TileMatrix = null;
}
else if (SetTileMatrix() || reset)
else if (SetTileMatrix() || tileSourceChanged)
{
if (tileSourceChanged)
{
Tiles.Clear();
}
UpdateRenderTransform();
UpdateTiles(reset);
BeginLoadTiles(Tiles, SourceName);
UpdateTiles();
BeginLoadTiles(Tiles, TileSource, SourceName);
}
}
private bool SetTileMatrix()
{
// Add 0.001 to avoid rounding issues.
// Add 0.001 to avoid floating point precision.
//
var tileMatrixZoomLevel = (int)Math.Floor(ParentMap.ZoomLevel - ZoomLevelOffset + 0.001);
var tileMatrixScale = MapBase.ZoomLevelToScale(tileMatrixZoomLevel);
@ -177,15 +200,9 @@ namespace MapControl
return true;
}
private void UpdateTiles(bool reset)
private void UpdateTiles()
{
var tiles = new ImageTileList();
if (reset)
{
Tiles.Clear();
}
var maxZoomLevel = Math.Min(TileMatrix.ZoomLevel, MaxZoomLevel);
if (maxZoomLevel >= MinZoomLevel)

View file

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
#if WPF
using System.Windows;
using System.Windows.Controls;
@ -19,7 +18,6 @@ using Microsoft.UI.Xaml.Hosting;
using Microsoft.UI.Xaml.Media;
#elif AVALONIA
using Avalonia.Controls;
using Avalonia.Media;
using Brush = Avalonia.Media.IBrush;
#endif
@ -27,10 +25,6 @@ namespace MapControl
{
public abstract class TilePyramidLayer : Panel, IMapLayer
{
public static readonly DependencyProperty TileSourceProperty =
DependencyPropertyHelper.Register<TilePyramidLayer, TileSource>(nameof(TileSource), null,
(layer, oldValue, newValue) => layer.UpdateTiles(true));
public static readonly DependencyProperty SourceNameProperty =
DependencyPropertyHelper.Register<TilePyramidLayer, string>(nameof(SourceName));
@ -83,15 +77,6 @@ namespace MapControl
set => tileImageLoader = value;
}
/// <summary>
/// Provides map tile URIs or images.
/// </summary>
public TileSource TileSource
{
get => (TileSource)GetValue(TileSourceProperty);
set => SetValue(TileSourceProperty, value);
}
/// <summary>
/// Name of the tile source that is used as component of a tile cache key.
/// Tile images are not cached when SourceName is null or empty.
@ -190,12 +175,9 @@ namespace MapControl
public abstract IReadOnlyCollection<string> SupportedCrsIds { get; }
protected void BeginLoadTiles(IEnumerable<Tile> tiles, string cacheName)
protected void BeginLoadTiles(IEnumerable<Tile> tiles, TileSource tileSource, string cacheName)
{
if (TileSource != null && tiles != null && tiles.Any(tile => tile.IsPending))
{
TileImageLoader.BeginLoadTiles(tiles, TileSource, cacheName, loadingProgress);
}
TileImageLoader.BeginLoadTiles(tiles, tileSource, cacheName, loadingProgress);
}
protected void CancelLoadTiles()
@ -206,12 +188,12 @@ namespace MapControl
protected abstract void UpdateRenderTransform();
protected abstract void UpdateTileCollection(bool reset);
protected abstract void UpdateTileCollection();
private void UpdateTiles(bool reset = false)
private void UpdateTiles()
{
updateTimer.Stop();
UpdateTileCollection(reset);
UpdateTileCollection();
}
private void OnViewportChanged(object sender, ViewportChangedEventArgs e)

View file

@ -47,7 +47,7 @@ namespace MapControl
}
else
{
throw new ArgumentException($"Invalid Capabilities URI: {uri}");
throw new ArgumentException($"Invalid Capabilities Uri: {uri}");
}
using var stream = xmlStream;

View file

@ -26,8 +26,10 @@ namespace MapControl
private static ILogger Logger => logger ??= ImageLoader.LoggerFactory?.CreateLogger(typeof(WmtsTileLayer));
public static readonly DependencyProperty CapabilitiesUriProperty =
DependencyPropertyHelper.Register<WmtsTileLayer, Uri>(nameof(CapabilitiesUri), null,
(layer, oldValue, newValue) => layer.TileMatrixSets.Clear());
DependencyPropertyHelper.Register<WmtsTileLayer, Uri>(nameof(CapabilitiesUri));
public static readonly DependencyProperty TileUriTemplateProperty =
DependencyPropertyHelper.Register<WmtsTileLayer, string>(nameof(TileUriTemplate));
public static readonly DependencyProperty LayerProperty =
DependencyPropertyHelper.Register<WmtsTileLayer, string>(nameof(Layer));
@ -50,7 +52,18 @@ namespace MapControl
}
/// <summary>
/// The Identifier of the Layer that should be displayed. If not set, the first Layer is displayed.
/// The Uri template string used for the UriTemplate property of WmtsTileSource instances.
/// Usually set internally from WmtsCapabilities requested by a Loaded event handler.
/// </summary>
public string TileUriTemplate
{
get => (string)GetValue(TileUriTemplateProperty);
set => SetValue(TileUriTemplateProperty, value);
}
/// <summary>
/// The Identifier of the Layer that should be displayed.
/// If not set, the value is defined by WmtsCapabilities.
/// </summary>
public string Layer
{
@ -108,10 +121,8 @@ namespace MapControl
}
}
protected override void UpdateTileCollection(bool reset)
protected override void UpdateTileCollection()
{
// reset parameter is ignored here because it is always false.
if (ParentMap == null ||
!TileMatrixSets.TryGetValue(ParentMap.MapProjection.CrsId, out WmtsTileMatrixSet tileMatrixSet))
{
@ -120,7 +131,11 @@ namespace MapControl
}
else if (UpdateChildLayers(tileMatrixSet))
{
((WmtsTileSource)TileSource).TileMatrixSet = tileMatrixSet;
var tileSource = new WmtsTileSource
{
UriTemplate = TileUriTemplate,
TileMatrixSet = tileMatrixSet
};
var cacheName = SourceName;
@ -137,7 +152,7 @@ namespace MapControl
}
}
BeginLoadTiles(ChildLayers.SelectMany(layer => layer.Tiles), cacheName);
BeginLoadTiles(ChildLayers.SelectMany(layer => layer.Tiles), tileSource, cacheName);
}
}
@ -148,13 +163,13 @@ namespace MapControl
//
var maxScale = 1.001 * ParentMap.ViewTransform.Scale;
var tileMatrixes = tileMatrixSet.TileMatrixes.Where(matrix => matrix.Scale <= maxScale).ToList();
var childLayers = ChildLayers.Where(layer => tileMatrixes.Contains(layer.WmtsTileMatrix)).ToList();
var tilesChanged = false;
Children.Clear();
if (tileMatrixes.Count > 0)
if (tileMatrixes.Count == 0)
{
Children.Clear();
return false;
}
var maxLayers = Math.Max(MaxBackgroundLevels, 0) + 1;
if (!IsBaseMapLayer)
@ -170,12 +185,18 @@ namespace MapControl
tileMatrixes = tileMatrixes.GetRange(tileMatrixes.Count - maxLayers, maxLayers);
}
// Get reusable layers.
//
var layers = ChildLayers.Where(layer => tileMatrixes.Contains(layer.WmtsTileMatrix)).ToList();
var tilesChanged = false;
Children.Clear();
foreach (var tileMatrix in tileMatrixes)
{
// Reuse existing WmtsTileMatrixLayer or create a new one with the
// index of tileMatrix in tileMatrixSet.TileMatrixes as zoom level.
// Pass index of tileMatrix in tileMatrixSet.TileMatrixes as zoom level to WmtsTileMatrixLayer ctor.
//
var layer = childLayers.FirstOrDefault(layer => layer.WmtsTileMatrix == tileMatrix) ??
var layer = layers.FirstOrDefault(layer => layer.WmtsTileMatrix == tileMatrix) ??
new WmtsTileMatrixLayer(tileMatrix, tileMatrixSet.TileMatrixes.IndexOf(tileMatrix));
if (layer.UpdateTiles(ParentMap.ViewTransform, ParentMap.ActualWidth, ParentMap.ActualHeight))
@ -187,7 +208,6 @@ namespace MapControl
Children.Add(layer);
}
}
return tilesChanged;
}
@ -211,7 +231,9 @@ namespace MapControl
}
Layer = capabilities.Layer;
TileSource = new WmtsTileSource { UriTemplate = capabilities.UriTemplate };
TileUriTemplate = capabilities.UriTemplate;
UpdateTileCollection();
}
catch (Exception ex)
{