From c46b6c1afa08f425b75a5a2f373f4cca8313aaf2 Mon Sep 17 00:00:00 2001 From: Clemens Date: Mon, 22 Aug 2022 21:13:45 +0200 Subject: [PATCH] Cleaner code, mainly WmsImageLayer --- MapControl/Shared/MapTileLayer.cs | 62 ++++----- MapControl/Shared/MapTileLayerBase.cs | 4 +- MapControl/Shared/WmsImageLayer.cs | 176 ++++++++++++-------------- MapControl/Shared/WmtsCapabilities.cs | 54 ++++---- 4 files changed, 137 insertions(+), 159 deletions(-) diff --git a/MapControl/Shared/MapTileLayer.cs b/MapControl/Shared/MapTileLayer.cs index 7946eb5c..7a3cdcc7 100644 --- a/MapControl/Shared/MapTileLayer.cs +++ b/MapControl/Shared/MapTileLayer.cs @@ -204,55 +204,57 @@ namespace MapControl private void UpdateTiles() { - var newTiles = new List(); - int maxZoomLevel; + var tiles = new List(); - 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); } diff --git a/MapControl/Shared/MapTileLayerBase.cs b/MapControl/Shared/MapTileLayerBase.cs index 249e5806..a9c42f86 100644 --- a/MapControl/Shared/MapTileLayerBase.cs +++ b/MapControl/Shared/MapTileLayerBase.cs @@ -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 } /// - /// 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. /// public int MaxBackgroundLevels diff --git a/MapControl/Shared/WmsImageLayer.cs b/MapControl/Shared/WmsImageLayer.cs index c8f1bcdc..b32aa70b 100644 --- a/MapControl/Shared/WmsImageLayer.cs +++ b/MapControl/Shared/WmsImageLayer.cs @@ -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 /// protected virtual string GetCapabilitiesRequestUri() { - return GetRequestUri("GetCapabilities").Replace(" ", "%20"); + return GetRequestUri(new Dictionary + { + { "SERVICE", "WMS" }, + { "VERSION", "1.3.0" }, + { "REQUEST", "GetCapabilities" } + }); } /// @@ -230,40 +235,29 @@ namespace MapControl /// 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 + { + { "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") } + }); } /// @@ -271,82 +265,72 @@ namespace MapControl /// 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 + { + { "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 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"); } } } diff --git a/MapControl/Shared/WmtsCapabilities.cs b/MapControl/Shared/WmtsCapabilities.cs index be230e59..e7971aa7 100644 --- a/MapControl/Shared/WmtsCapabilities.cs +++ b/MapControl/Shared/WmtsCapabilities.cs @@ -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))