Cleaner code, mainly WmsImageLayer

This commit is contained in:
Clemens 2022-08-22 21:13:45 +02:00
parent 4b4eecf810
commit c46b6c1afa
4 changed files with 137 additions and 159 deletions

View file

@ -204,55 +204,57 @@ namespace MapControl
private void UpdateTiles()
{
var newTiles = new List<Tile>();
int maxZoomLevel;
var tiles = new List<Tile>();
if (TileSource != null &&
TileMatrix != null &&
(maxZoomLevel = Math.Min(TileMatrix.ZoomLevel, MaxZoomLevel)) >= MinZoomLevel)
if (TileSource != null && TileMatrix != null)
{
var minZoomLevel = IsBaseMapLayer
? Math.Max(TileMatrix.ZoomLevel - MaxBackgroundLevels, MinZoomLevel)
: maxZoomLevel;
var maxZoomLevel = Math.Min(TileMatrix.ZoomLevel, MaxZoomLevel);
for (var z = minZoomLevel; z <= maxZoomLevel; z++)
if (maxZoomLevel >= MinZoomLevel)
{
var tileSize = 1 << (TileMatrix.ZoomLevel - z);
var x1 = (int)Math.Floor((double)TileMatrix.XMin / tileSize); // may be negative
var x2 = TileMatrix.XMax / tileSize;
var y1 = Math.Max(TileMatrix.YMin / tileSize, 0);
var y2 = Math.Min(TileMatrix.YMax / tileSize, (1 << z) - 1);
var minZoomLevel = IsBaseMapLayer
? Math.Max(TileMatrix.ZoomLevel - MaxBackgroundLevels, MinZoomLevel)
: maxZoomLevel;
for (var y = y1; y <= y2; y++)
for (var z = minZoomLevel; z <= maxZoomLevel; z++)
{
for (var x = x1; x <= x2; x++)
var tileSize = 1 << (TileMatrix.ZoomLevel - z);
var x1 = (int)Math.Floor((double)TileMatrix.XMin / tileSize); // may be negative
var x2 = TileMatrix.XMax / tileSize;
var y1 = Math.Max(TileMatrix.YMin / tileSize, 0);
var y2 = Math.Min(TileMatrix.YMax / tileSize, (1 << z) - 1);
for (var y = y1; y <= y2; y++)
{
var tile = Tiles.FirstOrDefault(t => t.ZoomLevel == z && t.X == x && t.Y == y);
if (tile == null)
for (var x = x1; x <= x2; x++)
{
tile = new Tile(z, x, y);
var tile = Tiles.FirstOrDefault(t => t.ZoomLevel == z && t.X == x && t.Y == y);
var equivalentTile = Tiles.FirstOrDefault(
t => t.ZoomLevel == z && t.XIndex == tile.XIndex && t.Y == y && !t.Pending);
if (equivalentTile != null)
if (tile == null)
{
tile.SetImage(equivalentTile.Image.Source, false); // no fade-in animation
}
}
tile = new Tile(z, x, y);
newTiles.Add(tile);
var equivalentTile = Tiles.FirstOrDefault(
t => t.ZoomLevel == z && t.XIndex == tile.XIndex && t.Y == y && !t.Pending);
if (equivalentTile != null)
{
tile.SetImage(equivalentTile.Image.Source, false); // no fade-in animation
}
}
tiles.Add(tile);
}
}
}
}
}
Tiles = newTiles;
Tiles = tiles;
Children.Clear();
foreach (var tile in Tiles)
foreach (var tile in tiles)
{
Children.Add(tile.Image);
}

View file

@ -45,7 +45,7 @@ namespace MapControl
nameof(Description), typeof(string), typeof(MapTileLayerBase), new PropertyMetadata(null));
public static readonly DependencyProperty MaxBackgroundLevelsProperty = DependencyProperty.Register(
nameof(MaxBackgroundLevels), typeof(int), typeof(MapTileLayerBase), new PropertyMetadata(8));
nameof(MaxBackgroundLevels), typeof(int), typeof(MapTileLayerBase), new PropertyMetadata(5));
public static readonly DependencyProperty UpdateIntervalProperty = DependencyProperty.Register(
nameof(UpdateInterval), typeof(TimeSpan), typeof(MapTileLayerBase),
@ -111,7 +111,7 @@ namespace MapControl
}
/// <summary>
/// Maximum number of background tile levels. Default value is 8.
/// Maximum number of background tile levels. Default value is 5.
/// Only effective in a MapTileLayer or WmtsTileLayer that is the MapLayer of its ParentMap.
/// </summary>
public int MaxBackgroundLevels

View file

@ -37,7 +37,7 @@ namespace MapControl
new PropertyMetadata(null,
async (o, e) =>
{
if (e.OldValue != null) // ignore initial property change from GetImageAsync
if (e.OldValue != null) // ignore property change from GetImageAsync
{
await ((WmsImageLayer)o).UpdateImageAsync();
}
@ -222,7 +222,12 @@ namespace MapControl
/// </summary>
protected virtual string GetCapabilitiesRequestUri()
{
return GetRequestUri("GetCapabilities").Replace(" ", "%20");
return GetRequestUri(new Dictionary<string, string>
{
{ "SERVICE", "WMS" },
{ "VERSION", "1.3.0" },
{ "REQUEST", "GetCapabilities" }
});
}
/// <summary>
@ -230,40 +235,29 @@ namespace MapControl
/// </summary>
protected virtual string GetMapRequestUri()
{
string uri = null;
var projection = ParentMap?.MapProjection;
if (projection != null)
if (projection == null)
{
uri = GetRequestUri("GetMap");
if (uri.IndexOf("LAYERS=", StringComparison.OrdinalIgnoreCase) < 0 && Layers != null)
{
uri += "&LAYERS=" + Layers;
}
if (uri.IndexOf("STYLES=", StringComparison.OrdinalIgnoreCase) < 0 && Styles != null)
{
uri += "&STYLES=" + Styles;
}
if (uri.IndexOf("FORMAT=", StringComparison.OrdinalIgnoreCase) < 0)
{
uri += "&FORMAT=image/png";
}
var mapRect = projection.BoundingBoxToRect(BoundingBox);
var viewScale = ParentMap.ViewTransform.Scale;
uri += "&" + GetCrsParam(projection);
uri += "&" + GetBboxParam(projection, mapRect);
uri += "&WIDTH=" + (int)Math.Round(viewScale * mapRect.Width);
uri += "&HEIGHT=" + (int)Math.Round(viewScale * mapRect.Height);
uri = uri.Replace(" ", "%20");
return null;
}
return uri;
var mapRect = projection.BoundingBoxToRect(BoundingBox);
var viewScale = ParentMap.ViewTransform.Scale;
return GetRequestUri(new Dictionary<string, string>
{
{ "SERVICE", "WMS" },
{ "VERSION", "1.3.0" },
{ "REQUEST", "GetMap" },
{ "LAYERS", Layers ?? "" },
{ "STYLES", Styles ?? "" },
{ "FORMAT", "image/png" },
{ "CRS", GetCrsValue(projection) },
{ "BBOX", GetBboxValue(projection, mapRect) },
{ "WIDTH", Math.Round(viewScale * mapRect.Width).ToString("F0") },
{ "HEIGHT", Math.Round(viewScale * mapRect.Height).ToString("F0") }
});
}
/// <summary>
@ -271,82 +265,72 @@ namespace MapControl
/// </summary>
protected virtual string GetFeatureInfoRequestUri(Point position, string format)
{
string uri = null;
var projection = ParentMap?.MapProjection;
if (projection != null)
if (projection == null)
{
uri = GetRequestUri("GetFeatureInfo");
return null;
}
var i = uri.IndexOf("LAYERS=", StringComparison.OrdinalIgnoreCase);
var mapRect = projection.BoundingBoxToRect(BoundingBox);
var viewRect = GetViewRect(mapRect);
var viewSize = ParentMap.RenderSize;
if (i >= 0)
var transform = new Matrix(1, 0, 0, 1, -viewSize.Width / 2, -viewSize.Height / 2);
transform.Rotate(-viewRect.Rotation);
transform.Translate(viewRect.Width / 2, viewRect.Height / 2);
var imagePos = transform.Transform(position);
var queryParameters = new Dictionary<string, string>
{
{ "SERVICE", "WMS" },
{ "VERSION", "1.3.0" },
{ "REQUEST", "GetFeatureInfo" },
{ "LAYERS", Layers ?? "" },
{ "STYLES", Styles ?? "" },
{ "FORMAT", "image/png" },
{ "INFO_FORMAT", format },
{ "CRS", GetCrsValue(projection) },
{ "BBOX", GetBboxValue(projection, mapRect) },
{ "WIDTH", Math.Round(viewRect.Width).ToString("F0") },
{ "HEIGHT", Math.Round(viewRect.Height).ToString("F0") },
{ "I", Math.Round(imagePos.X).ToString("F0") },
{ "J", Math.Round(imagePos.Y).ToString("F0") }
};
return GetRequestUri(queryParameters) + "&QUERY_LAYERS=" + queryParameters["LAYERS"];
}
protected virtual string GetCrsValue(MapProjection projection)
{
return projection.GetCrsValue();
}
protected virtual string GetBboxValue(MapProjection projection, Rect mapRect)
{
return projection.GetBboxValue(mapRect);
}
protected string GetRequestUri(IDictionary<string, string> queryParameters)
{
var query = ServiceUri.Query;
if (!string.IsNullOrEmpty(query))
{
foreach (var param in query.Substring(1).Split('&'))
{
i += "LAYERS=".Length;
var j = uri.IndexOf('&', i);
var layers = j >= i ? uri.Substring(i, j - i) : uri.Substring(i);
uri += "&QUERY_LAYERS=" + layers;
var pair = param.Split('=');
queryParameters[pair[0].ToUpper()] = pair.Length > 1 ? pair[1] : "";
}
else if (Layers != null)
{
uri += "&LAYERS=" + Layers;
uri += "&QUERY_LAYERS=" + Layers;
}
var mapRect = projection.BoundingBoxToRect(BoundingBox);
var viewRect = GetViewRect(mapRect);
var viewSize = ParentMap.RenderSize;
var transform = new Matrix(1, 0, 0, 1, -viewSize.Width / 2, -viewSize.Height / 2);
transform.Rotate(-viewRect.Rotation);
transform.Translate(viewRect.Width / 2, viewRect.Height / 2);
var imagePos = transform.Transform(position);
uri += "&" + GetCrsParam(projection);
uri += "&" + GetBboxParam(projection, mapRect);
uri += "&WIDTH=" + (int)Math.Round(viewRect.Width);
uri += "&HEIGHT=" + (int)Math.Round(viewRect.Height);
uri += "&I=" + (int)Math.Round(imagePos.X);
uri += "&J=" + (int)Math.Round(imagePos.Y);
uri += "&INFO_FORMAT=" + format;
uri = uri.Replace(" ", "%20");
}
return uri;
}
var uri = ServiceUri.GetLeftPart(UriPartial.Path) + "?"
+ string.Join("&", queryParameters.Select(kv => kv.Key + "=" + kv.Value));
protected virtual string GetCrsParam(MapProjection projection)
{
return "CRS=" + projection.GetCrsValue();
}
Debug.WriteLine(uri);
protected virtual string GetBboxParam(MapProjection projection, Rect mapRect)
{
return "BBOX=" + projection.GetBboxValue(mapRect);
}
protected string GetRequestUri(string request)
{
var uri = ServiceUri.ToString();
if (!uri.EndsWith("?") && !uri.EndsWith("&"))
{
uri += !uri.Contains("?") ? "?" : "&";
}
if (uri.IndexOf("SERVICE=", StringComparison.OrdinalIgnoreCase) < 0)
{
uri += "SERVICE=WMS&";
}
if (uri.IndexOf("VERSION=", StringComparison.OrdinalIgnoreCase) < 0)
{
uri += "VERSION=1.3.0&";
}
return uri + "REQUEST=" + request;
return uri.Replace(" ", "%20");
}
}
}

View file

@ -133,44 +133,36 @@ namespace MapControl
if (resourceUrls.Any())
{
var urlTemplates
= resourceUrls.Contains(formatPng) ? resourceUrls[formatPng]
: resourceUrls.Contains(formatJpg) ? resourceUrls[formatJpg]
: resourceUrls.First();
var urlTemplates = resourceUrls.Contains(formatPng) ? resourceUrls[formatPng]
: resourceUrls.Contains(formatJpg) ? resourceUrls[formatJpg]
: resourceUrls.First();
urlTemplate = urlTemplates.First().Replace("{Style}", style);
}
else if (capabilitiesUrl != null)
else if (capabilitiesUrl != null &&
capabilitiesUrl.IndexOf("Request=GetCapabilities", StringComparison.OrdinalIgnoreCase) >= 0)
{
const string requestParam = "Request=GetCapabilities";
var requestIndex = capabilitiesUrl.IndexOf(requestParam, StringComparison.OrdinalIgnoreCase);
var formats = layerElement.Descendants(ns + "Format").Select(e => e.Value).ToList();
var format = formatPng;
if (requestIndex > 0)
if (formats.Count > 0)
{
var formats = layerElement.Descendants(ns + "Format").Select(e => e.Value).ToList();
if (formats.Count == 0)
{
throw new ArgumentException($"No Format element found in Layer \"{layerIdentifier}\".");
}
var format
= formats.Contains(formatPng) ? formatPng
: formats.Contains(formatJpg) ? formatJpg
: formats[0];
urlTemplate = capabilitiesUrl.Substring(0, requestIndex)
+ "Request=GetTile"
+ capabilitiesUrl.Substring(requestIndex + requestParam.Length)
+ "&Version=1.0.0"
+ "&Layer=" + layerIdentifier
+ "&Format=" + format
+ "&Style=" + style
+ "&TileMatrixSet={TileMatrixSet}"
+ "&TileMatrix={TileMatrix}"
+ "&TileCol={TileCol}"
+ "&TileRow={TileRow}";
format = formats.Contains(formatPng) ? formatPng
: formats.Contains(formatJpg) ? formatJpg
: formats[0];
}
urlTemplate = capabilitiesUrl.Split('?')[0]
+ "?Service=WMTS"
+ "&Request=GetTile"
+ "&Version=1.0.0"
+ "&Layer=" + layerIdentifier
+ "&Style=" + style
+ "&Format=" + format
+ "&TileMatrixSet={TileMatrixSet}"
+ "&TileMatrix={TileMatrix}"
+ "&TileRow={TileRow}"
+ "&TileCol={TileCol}";
}
if (string.IsNullOrEmpty(urlTemplate))