Simplified WMS/WMTS layers

This commit is contained in:
ClemensFischer 2022-11-25 19:05:48 +01:00
parent afc93704d9
commit 370618f66f
5 changed files with 66 additions and 106 deletions

View file

@ -165,29 +165,27 @@ namespace MapControl
protected override async void OnViewportChanged(ViewportChangedEventArgs e) protected override async void OnViewportChanged(ViewportChangedEventArgs e)
{ {
base.OnViewportChanged(e);
if (e.ProjectionChanged) if (e.ProjectionChanged)
{ {
ClearImages(); ClearImages();
base.OnViewportChanged(e);
await UpdateImageAsync(); // update immediately await UpdateImageAsync(); // update immediately
} }
else else
{ {
ValidateBoundingBox();
base.OnViewportChanged(e);
updateTimer.Run(!UpdateWhileViewportChanging); updateTimer.Run(!UpdateWhileViewportChanging);
} }
} }
protected async Task UpdateImageAsync() protected async Task UpdateImageAsync()
{ {
if (updateInProgress) // update image on next tick if (updateInProgress)
{ {
updateTimer.Run(); // start timer if not running // update image on next tick, start timer if not running
//
updateTimer.Run();
} }
else else
{ {
@ -233,35 +231,6 @@ namespace MapControl
BoundingBox = ParentMap.ViewRectToBoundingBox(rect); BoundingBox = ParentMap.ViewRectToBoundingBox(rect);
} }
private void ValidateBoundingBox()
{
if (BoundingBox != null)
{
var offset = ParentMap.Center.Longitude - BoundingBox.Center.Longitude;
if (Math.Abs(offset) > 180d)
{
offset = 360d * Math.Sign(offset);
BoundingBox = new BoundingBox(
BoundingBox.South, BoundingBox.West + offset,
BoundingBox.North, BoundingBox.East + offset);
foreach (var image in Children.OfType<Image>())
{
var imageBbox = GetBoundingBox(image);
if (imageBbox != null)
{
SetBoundingBox(image, new BoundingBox(
imageBbox.South, imageBbox.West + offset,
imageBbox.North, imageBbox.East + offset));
}
}
}
}
}
private void ClearImages() private void ClearImages()
{ {
foreach (var image in Children.OfType<Image>()) foreach (var image in Children.OfType<Image>())

View file

@ -3,7 +3,6 @@
// Licensed under the Microsoft Public License (Ms-PL) // Licensed under the Microsoft Public License (Ms-PL)
using System; using System;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
#if WINUI #if WINUI
using Windows.Foundation; using Windows.Foundation;
@ -149,7 +148,14 @@ namespace MapControl
SetRenderTransform(); SetRenderTransform();
} }
return updateTiles ? UpdateTiles() : Task.CompletedTask; if (updateTiles)
{
UpdateTiles();
return TileImageLoader.LoadTiles(Tiles, TileSource, SourceName);
}
return Task.CompletedTask;
} }
protected override void SetRenderTransform() protected override void SetRenderTransform()
@ -197,7 +203,7 @@ namespace MapControl
return true; return true;
} }
private Task UpdateTiles() private void UpdateTiles()
{ {
var tiles = new TileCollection(); var tiles = new TileCollection();
@ -239,8 +245,6 @@ namespace MapControl
{ {
Children.Add(tile.Image); Children.Add(tile.Image);
} }
return TileImageLoader.LoadTiles(tiles, TileSource, SourceName);
} }
} }
} }

View file

@ -201,7 +201,7 @@ namespace MapControl
private async void OnViewportChanged(object sender, ViewportChangedEventArgs e) private async void OnViewportChanged(object sender, ViewportChangedEventArgs e)
{ {
if (Children.Count == 0 || e.ProjectionChanged || e.TransformCenterChanged) if (e.TransformCenterChanged || e.ProjectionChanged || Children.Count == 0)
{ {
await Update(); // update immediately await Update(); // update immediately
} }

View file

@ -91,14 +91,15 @@ namespace MapControl
{ {
Children.Clear(); Children.Clear();
return UpdateTiles(null); return LoadTiles(null); // stop TileImageLoader
} }
var updateTiles = UpdateChildLayers(tileMatrixSet); if (UpdateChildLayers(tileMatrixSet))
{
return LoadTiles(tileMatrixSet);
}
SetRenderTransform(); return Task.CompletedTask;
return updateTiles ? UpdateTiles(tileMatrixSet) : Task.CompletedTask;
} }
protected override void SetRenderTransform() protected override void SetRenderTransform()
@ -111,7 +112,6 @@ namespace MapControl
private bool UpdateChildLayers(WmtsTileMatrixSet tileMatrixSet) private bool UpdateChildLayers(WmtsTileMatrixSet tileMatrixSet)
{ {
var layersChanged = false;
var maxScale = 1.001 * ParentMap.ViewTransform.Scale; // avoid rounding issues var maxScale = 1.001 * ParentMap.ViewTransform.Scale; // avoid rounding issues
// show all WmtsTileMatrix layers with Scale <= maxScale, at least the first layer // show all WmtsTileMatrix layers with Scale <= maxScale, at least the first layer
@ -129,42 +129,33 @@ namespace MapControl
currentMatrixes = currentMatrixes.Skip(currentMatrixes.Count - MaxBackgroundLevels - 1).ToList(); currentMatrixes = currentMatrixes.Skip(currentMatrixes.Count - MaxBackgroundLevels - 1).ToList();
} }
var currentLayers = ChildLayers.Where(layer => currentMatrixes.Contains(layer.TileMatrix)).ToList(); var currentLayers = ChildLayers.Where(layer => currentMatrixes.Contains(layer.WmtsTileMatrix)).ToList();
var tilesChanged = false;
Children.Clear(); Children.Clear();
foreach (var tileMatrix in currentMatrixes) foreach (var tileMatrix in currentMatrixes)
{ {
var layer = currentLayers.FirstOrDefault(l => l.TileMatrix == tileMatrix); var layer = currentLayers.FirstOrDefault(l => l.WmtsTileMatrix == tileMatrix)
?? new WmtsTileMatrixLayer(tileMatrix, tileMatrixSet.TileMatrixes.IndexOf(tileMatrix));
if (layer == null) if (layer.UpdateTiles(ParentMap.ViewTransform, ParentMap.RenderSize))
{ {
layer = new WmtsTileMatrixLayer(tileMatrix, tileMatrixSet.TileMatrixes.IndexOf(tileMatrix)); tilesChanged = true;
layersChanged = true;
} }
if (layer.SetBounds(ParentMap.ViewTransform, ParentMap.RenderSize)) layer.SetRenderTransform(ParentMap.ViewTransform);
{
layersChanged = true;
}
Children.Add(layer); Children.Add(layer);
} }
return layersChanged; return tilesChanged;
} }
private Task UpdateTiles(WmtsTileMatrixSet tileMatrixSet) private Task LoadTiles(WmtsTileMatrixSet tileMatrixSet)
{ {
var tiles = new List<Tile>();
var cacheName = SourceName; var cacheName = SourceName;
foreach (var layer in ChildLayers)
{
layer.UpdateTiles();
tiles.AddRange(layer.Tiles);
}
if (tileMatrixSet != null && TileSource is WmtsTileSource tileSource) if (tileMatrixSet != null && TileSource is WmtsTileSource tileSource)
{ {
tileSource.TileMatrixSet = tileMatrixSet; tileSource.TileMatrixSet = tileMatrixSet;
@ -180,6 +171,8 @@ namespace MapControl
} }
} }
var tiles = ChildLayers.SelectMany(layer => layer.Tiles);
return TileImageLoader.LoadTiles(tiles, TileSource, cacheName); return TileImageLoader.LoadTiles(tiles, TileSource, cacheName);
} }

View file

@ -21,21 +21,18 @@ namespace MapControl
{ {
public class WmtsTileMatrixLayer : Panel public class WmtsTileMatrixLayer : Panel
{ {
// zoomLevel is index of tileMatrix in a WmtsTileMatrixSet.TileMatrixes list
//
public WmtsTileMatrixLayer(WmtsTileMatrix tileMatrix, int zoomLevel) public WmtsTileMatrixLayer(WmtsTileMatrix tileMatrix, int zoomLevel)
{ {
RenderTransform = new MatrixTransform(); RenderTransform = new MatrixTransform();
TileMatrix = tileMatrix; WmtsTileMatrix = tileMatrix;
ZoomLevel = zoomLevel; TileMatrix = new TileMatrix(zoomLevel, 1, 1, 0, 0);
} }
public WmtsTileMatrix TileMatrix { get; } public WmtsTileMatrix WmtsTileMatrix { get; }
public int ZoomLevel { get; } // index of TileMatrix in WmtsTileMatrixSet.TileMatrixes public TileMatrix TileMatrix { get; private set; }
public int XMin { get; private set; }
public int YMin { get; private set; }
public int XMax { get; private set; }
public int YMax { get; private set; }
public TileCollection Tiles { get; private set; } = new TileCollection(); public TileCollection Tiles { get; private set; } = new TileCollection();
@ -43,62 +40,57 @@ namespace MapControl
{ {
// tile matrix origin in pixels // tile matrix origin in pixels
// //
var tileMatrixOrigin = new Point(TileMatrix.TileWidth * XMin, TileMatrix.TileHeight * YMin); var tileMatrixOrigin = new Point(WmtsTileMatrix.TileWidth * TileMatrix.XMin, WmtsTileMatrix.TileHeight * TileMatrix.YMin);
((MatrixTransform)RenderTransform).Matrix = ((MatrixTransform)RenderTransform).Matrix =
viewTransform.GetTileLayerTransform(TileMatrix.Scale, TileMatrix.TopLeft, tileMatrixOrigin); viewTransform.GetTileLayerTransform(WmtsTileMatrix.Scale, WmtsTileMatrix.TopLeft, tileMatrixOrigin);
} }
public bool SetBounds(ViewTransform viewTransform, Size viewSize) public bool UpdateTiles(ViewTransform viewTransform, Size viewSize)
{ {
// bounds in tile pixels from view size // bounds in tile pixels from view size
// //
var bounds = viewTransform.GetTileMatrixBounds(TileMatrix.Scale, TileMatrix.TopLeft, viewSize); var bounds = viewTransform.GetTileMatrixBounds(WmtsTileMatrix.Scale, WmtsTileMatrix.TopLeft, viewSize);
// tile X and Y bounds // tile X and Y bounds
// //
var xMin = (int)Math.Floor(bounds.X / TileMatrix.TileWidth); var xMin = (int)Math.Floor(bounds.X / WmtsTileMatrix.TileWidth);
var yMin = (int)Math.Floor(bounds.Y / TileMatrix.TileHeight); var yMin = (int)Math.Floor(bounds.Y / WmtsTileMatrix.TileHeight);
var xMax = (int)Math.Floor((bounds.X + bounds.Width) / TileMatrix.TileWidth); var xMax = (int)Math.Floor((bounds.X + bounds.Width) / WmtsTileMatrix.TileWidth);
var yMax = (int)Math.Floor((bounds.Y + bounds.Height) / TileMatrix.TileHeight); var yMax = (int)Math.Floor((bounds.Y + bounds.Height) / WmtsTileMatrix.TileHeight);
// total tile matrix width in meters // total tile matrix width in meters
// //
var totalWidth = TileMatrix.MatrixWidth * TileMatrix.TileWidth / TileMatrix.Scale; var totalWidth = WmtsTileMatrix.MatrixWidth * WmtsTileMatrix.TileWidth / WmtsTileMatrix.Scale;
if (Math.Abs(totalWidth - 360d * MapProjection.Wgs84MeterPerDegree) > 1d) if (Math.Abs(totalWidth - 360d * MapProjection.Wgs84MeterPerDegree) > 1d)
{ {
// no full longitudinal coverage, restrict x index // no full longitudinal coverage, restrict x index
// //
xMin = Math.Max(xMin, 0); xMin = Math.Max(xMin, 0);
xMax = Math.Min(Math.Max(xMax, 0), TileMatrix.MatrixWidth - 1); xMax = Math.Min(Math.Max(xMax, 0), WmtsTileMatrix.MatrixWidth - 1);
} }
yMin = Math.Max(yMin, 0); yMin = Math.Max(yMin, 0);
yMax = Math.Min(Math.Max(yMax, 0), TileMatrix.MatrixHeight - 1); yMax = Math.Min(Math.Max(yMax, 0), WmtsTileMatrix.MatrixHeight - 1);
if (XMin == xMin && YMin == yMin && XMax == xMax && YMax == yMax) if (TileMatrix.XMin == xMin && TileMatrix.YMin == yMin &&
TileMatrix.XMax == xMax && TileMatrix.YMax == yMax)
{ {
// no change of the TileMatrix and the Tiles collection
//
return false; return false;
} }
XMin = xMin; TileMatrix = new TileMatrix(TileMatrix.ZoomLevel, xMin, yMin, xMax, yMax);
YMin = yMin;
XMax = xMax;
YMax = yMax;
return true;
}
public void UpdateTiles()
{
var tiles = new TileCollection(); var tiles = new TileCollection();
for (var y = YMin; y <= YMax; y++) for (var y = yMin; y <= yMax; y++)
{ {
for (var x = XMin; x <= XMax; x++) for (var x = xMin; x <= xMax; x++)
{ {
tiles.Add(Tiles.GetTile(ZoomLevel, x, y, TileMatrix.MatrixWidth)); tiles.Add(Tiles.GetTile(TileMatrix.ZoomLevel, x, y, WmtsTileMatrix.MatrixWidth));
} }
} }
@ -106,10 +98,12 @@ namespace MapControl
Children.Clear(); Children.Clear();
foreach (var tile in Tiles) foreach (var tile in tiles)
{ {
Children.Add(tile.Image); Children.Add(tile.Image);
} }
return true;
} }
protected override Size MeasureOverride(Size availableSize) protected override Size MeasureOverride(Size availableSize)
@ -130,12 +124,12 @@ namespace MapControl
{ {
// arrange tiles relative to XMin/YMin // arrange tiles relative to XMin/YMin
// //
var x = TileMatrix.TileWidth * (tile.X - XMin); var x = WmtsTileMatrix.TileWidth * (tile.X - TileMatrix.XMin);
var y = TileMatrix.TileHeight * (tile.Y - YMin); var y = WmtsTileMatrix.TileHeight * (tile.Y - TileMatrix.YMin);
tile.Image.Width = TileMatrix.TileWidth; tile.Image.Width = WmtsTileMatrix.TileWidth;
tile.Image.Height = TileMatrix.TileHeight; tile.Image.Height = WmtsTileMatrix.TileHeight;
tile.Image.Arrange(new Rect(x, y, TileMatrix.TileWidth, TileMatrix.TileHeight)); tile.Image.Arrange(new Rect(x, y, WmtsTileMatrix.TileWidth, WmtsTileMatrix.TileHeight));
} }
return finalSize; return finalSize;