diff --git a/MapControl/Shared/AzimuthalProjection.cs b/MapControl/Shared/AzimuthalProjection.cs index 49f9ba80..e0a039d0 100644 --- a/MapControl/Shared/AzimuthalProjection.cs +++ b/MapControl/Shared/AzimuthalProjection.cs @@ -60,7 +60,7 @@ namespace MapControl base.SetViewportTransform(projectionCenter, mapCenter, viewportCenter, zoomLevel, heading); } - public override string WmsQueryParameters(BoundingBox boundingBox, string version) + public override string WmsQueryParameters(BoundingBox boundingBox, bool useSrs) { if (string.IsNullOrEmpty(CrsId)) { @@ -70,11 +70,11 @@ namespace MapControl var rect = BoundingBoxToRect(boundingBox); var width = (int)Math.Round(ViewportScale * rect.Width); var height = (int)Math.Round(ViewportScale * rect.Height); - var crs = version.StartsWith("1.1.") ? "SRS" : "CRS"; return string.Format(CultureInfo.InvariantCulture, "{0}={1},1,{2},{3}&BBOX={4},{5},{6},{7}&WIDTH={8}&HEIGHT={9}", - crs, CrsId, ProjectionCenter.Longitude, ProjectionCenter.Latitude, + (useSrs ? "SRS" : "CRS"), CrsId, + ProjectionCenter.Longitude, ProjectionCenter.Latitude, rect.X, rect.Y, (rect.X + rect.Width), (rect.Y + rect.Height), width, height); } diff --git a/MapControl/Shared/MapProjection.cs b/MapControl/Shared/MapProjection.cs index 56d45123..e6fb52b8 100644 --- a/MapControl/Shared/MapProjection.cs +++ b/MapControl/Shared/MapProjection.cs @@ -147,19 +147,18 @@ namespace MapControl } /// - /// Gets a WMS 1.3.0 query parameter string from the specified bounding box, - /// e.g. "CRS=...&BBOX=...&WIDTH=...&HEIGHT=..." + /// Gets a WMS query parameter string from the specified bounding box, e.g. "CRS=...&BBOX=...&WIDTH=...&HEIGHT=..." /// - public virtual string WmsQueryParameters(BoundingBox boundingBox, string version = "1.3.0") + public virtual string WmsQueryParameters(BoundingBox boundingBox, bool useSrs = false) { if (string.IsNullOrEmpty(CrsId) || !boundingBox.HasValidBounds) { return null; } - var format = "CRS={0}&BBOX={1},{2},{3},{4}&WIDTH={5}&HEIGHT={6}"; + string format; - if (version.StartsWith("1.1.")) + if (useSrs) { format = "SRS={0}&BBOX={1},{2},{3},{4}&WIDTH={5}&HEIGHT={6}"; } @@ -167,6 +166,10 @@ namespace MapControl { format = "CRS={0}&BBOX={2},{1},{4},{3}&WIDTH={5}&HEIGHT={6}"; } + else + { + format = "CRS={0}&BBOX={1},{2},{3},{4}&WIDTH={5}&HEIGHT={6}"; + } var rect = BoundingBoxToRect(boundingBox); var width = (int)Math.Round(ViewportScale * rect.Width); diff --git a/MapControl/Shared/WmsImageLayer.cs b/MapControl/Shared/WmsImageLayer.cs index 72183afd..6810044e 100644 --- a/MapControl/Shared/WmsImageLayer.cs +++ b/MapControl/Shared/WmsImageLayer.cs @@ -21,13 +21,15 @@ namespace MapControl { public partial class WmsImageLayer : MapImageLayer { - public static readonly DependencyProperty ServerUriProperty = DependencyProperty.Register( - nameof(ServerUri), typeof(Uri), typeof(WmsImageLayer), + private const string DefaultVersion = "1.3.0"; + + public static readonly DependencyProperty ServiceUriProperty = DependencyProperty.Register( + nameof(ServiceUri), typeof(Uri), typeof(WmsImageLayer), new PropertyMetadata(null, async (o, e) => await ((WmsImageLayer)o).UpdateImageAsync())); public static readonly DependencyProperty VersionProperty = DependencyProperty.Register( nameof(Version), typeof(string), typeof(WmsImageLayer), - new PropertyMetadata("1.3.0", async (o, e) => await ((WmsImageLayer)o).UpdateImageAsync())); + new PropertyMetadata(DefaultVersion, async (o, e) => await ((WmsImageLayer)o).UpdateImageAsync())); public static readonly DependencyProperty LayersProperty = DependencyProperty.Register( nameof(Layers), typeof(string), typeof(WmsImageLayer), @@ -41,16 +43,12 @@ namespace MapControl nameof(Format), typeof(string), typeof(WmsImageLayer), new PropertyMetadata("image/png", async (o, e) => await ((WmsImageLayer)o).UpdateImageAsync())); - public static readonly DependencyProperty TransparentProperty = DependencyProperty.Register( - nameof(Transparent), typeof(bool), typeof(WmsImageLayer), - new PropertyMetadata(false, async (o, e) => await ((WmsImageLayer)o).UpdateImageAsync())); - private string layers = string.Empty; - public Uri ServerUri + public Uri ServiceUri { - get { return (Uri)GetValue(ServerUriProperty); } - set { SetValue(ServerUriProperty, value); } + get { return (Uri)GetValue(ServiceUriProperty); } + set { SetValue(ServiceUriProperty, value); } } public string Version @@ -77,32 +75,38 @@ namespace MapControl set { SetValue(FormatProperty, value); } } - public bool Transparent - { - get { return (bool)GetValue(TransparentProperty); } - set { SetValue(TransparentProperty, value); } - } - protected override async Task GetImageAsync(BoundingBox boundingBox) { ImageSource imageSource = null; - if (ServerUri != null) + if (ServiceUri != null) { - var projectionParameters = ParentMap.MapProjection.WmsQueryParameters(boundingBox, Version); + var version = Version; + var uri = GetRequestUri(ref version) + "REQUEST=GetMap&"; + var projectionParameters = ParentMap.MapProjection.WmsQueryParameters(boundingBox, version.StartsWith("1.1.")); if (!string.IsNullOrEmpty(projectionParameters)) { - var uri = GetRequestUri("GetMap" - + "&LAYERS=" + Layers - + "&STYLES=" + Styles - + "&FORMAT=" + Format - + "&TRANSPARENT=" + (Transparent ? "TRUE" : "FALSE") - + "&" + projectionParameters); + if (uri.IndexOf("LAYERS=", StringComparison.OrdinalIgnoreCase) < 0) + { + uri += "LAYERS=" + (Layers ?? "") + "&"; + } + + if (uri.IndexOf("STYLES=", StringComparison.OrdinalIgnoreCase) < 0) + { + uri += "STYLES=" + (Styles ?? "") + "&"; + } + + if (uri.IndexOf("FORMAT=", StringComparison.OrdinalIgnoreCase) < 0) + { + uri += "FORMAT=" + (Format ?? "") + "&"; + } + + uri += projectionParameters; try { - imageSource = await ImageLoader.LoadImageAsync(uri, false); + imageSource = await ImageLoader.LoadImageAsync(new Uri(uri.Replace(" ", "%20")), false); } catch (Exception ex) { @@ -116,54 +120,76 @@ namespace MapControl public async Task> GetLayerNamesAsync() { - if (ServerUri == null) + IList layerNames = null; + + if (ServiceUri != null) { - return null; - } + var version = Version; + var uri = GetRequestUri(ref version) + "REQUEST=GetCapabilities"; - var layerNames = new List(); - - try - { - var document = await XmlDocument.LoadFromUriAsync(GetRequestUri("GetCapabilities")); - - var capability = ChildElements(document.DocumentElement, "Capability").FirstOrDefault(); - if (capability != null) + try { - var rootLayer = ChildElements(capability, "Layer").FirstOrDefault(); - if (rootLayer != null) + var document = await XmlDocument.LoadFromUriAsync(new Uri(uri.Replace(" ", "%20"))); + layerNames = new List(); + + var capability = ChildElements(document.DocumentElement, "Capability").FirstOrDefault(); + if (capability != null) { - foreach (var layer in ChildElements(rootLayer, "Layer")) + var rootLayer = ChildElements(capability, "Layer").FirstOrDefault(); + if (rootLayer != null) { - var name = ChildElements(layer, "Name").FirstOrDefault(); - if (name != null) + foreach (var layer in ChildElements(rootLayer, "Layer")) { - layerNames.Add(name.InnerText); + var name = ChildElements(layer, "Name").FirstOrDefault(); + if (name != null) + { + layerNames.Add(name.InnerText); + } } } } } - } - catch (Exception ex) - { - Debug.WriteLine("WmsImageLayer: {0}: {1}", ServerUri, ex.Message); + catch (Exception ex) + { + Debug.WriteLine("WmsImageLayer: {0}: {1}", uri, ex.Message); + } } return layerNames; } - private Uri GetRequestUri(string query) + private string GetRequestUri(ref string version) { - var uri = ServerUri.ToString(); + if (version == null) + { + version = DefaultVersion; + } + + var uri = ServiceUri.ToString(); if (!uri.EndsWith("?") && !uri.EndsWith("&")) { - uri += "?"; + uri += !uri.Contains("?") ? "?" : "&"; } - uri += "SERVICE=WMS&VERSION=" + Version + "&REQUEST=" + query; + if (uri.IndexOf("SERVICE=", StringComparison.OrdinalIgnoreCase) < 0) + { + uri += "SERVICE=WMS&"; + } - return new Uri(uri.Replace(" ", "%20")); + int versionStart = uri.IndexOf("VERSION=", StringComparison.OrdinalIgnoreCase); + int versionEnd; + + if (versionStart < 0) + { + uri += "VERSION=" + version + "&"; + } + else if ((versionEnd = uri.IndexOf("&", versionStart + 8)) >= versionStart + 8) + { + version = uri.Substring(versionStart, versionEnd - versionStart); + } + + return uri; } private static IEnumerable ChildElements(XmlElement element, string name) diff --git a/SampleApps/Shared/MapLayers.cs b/SampleApps/Shared/MapLayers.cs index 57573814..953a010c 100644 --- a/SampleApps/Shared/MapLayers.cs +++ b/SampleApps/Shared/MapLayers.cs @@ -99,8 +99,7 @@ namespace ViewModel new WmsImageLayer { Description = "© [terrestris GmbH & Co. KG](http://ows.terrestris.de/)\nData © [OpenStreetMap contributors](http://www.openstreetmap.org/copyright)", - ServerUri = new Uri("http://ows.terrestris.de/osm/service"), - Layers = "OSM-WMS" + ServiceUri = new Uri("http://ows.terrestris.de/osm/service?SERVICE=WMS&VERSION=1.3.0&LAYERS=OSM-WMS&STYLES=&FORMAT=image/png") } }, { @@ -108,8 +107,7 @@ namespace ViewModel new WmsImageLayer { Description = "© [terrestris GmbH & Co. KG](http://ows.terrestris.de/)\nData © [OpenStreetMap contributors](http://www.openstreetmap.org/copyright)", - ServerUri = new Uri("http://ows.terrestris.de/osm/service"), - Layers = "TOPO-OSM-WMS" + ServiceUri = new Uri("http://ows.terrestris.de/osm/service?SERVICE=WMS&VERSION=1.3.0&LAYERS=TOPO-OSM-WMS&STYLES=&FORMAT=image/png") } }, { @@ -117,8 +115,7 @@ namespace ViewModel new WmsImageLayer { Description = "© [SevenCs GmbH](http://www.sevencs.com)", - ServerUri = new Uri("http://chartserver4.sevencs.com:8080"), - Layers = "ENC", + ServiceUri = new Uri("http://chartserver4.sevencs.com:8080?SERVICE=WMS&VERSION=1.3.0&LAYERS=ENC&STYLES=&FORMAT=image/png"), MaxBoundingBoxWidth = 360 } }