TerriaJS / terriajs

A library for building rich, web-based geospatial data platforms.
https://terria.io
Apache License 2.0
1.18k stars 362 forks source link

Use the WMS LegendURL to show the legend #699

Closed meh9 closed 8 years ago

meh9 commented 9 years ago

Currently when showing a WMS layer Terria creates its own URL to get the WMS legend instead of using the one specified in the WMS GetCapabilities. This can be a problem when a service specifies a custom legend to use, as we then do not show it. See for example:

http://www.ga.gov.au/gis/services/topography/National_Electricity_Transmission_Lines/MapServer/WMSServer?request=GetCapabilities&service=WMS

<LegendURL width="173" height="377">
<Format>image/png</Format>
<OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.ga.gov.au/gis/server/capabilities/National_Electricity_Transmission_Lines.png" xlink:type="simple"/>
</LegendURL>
kring commented 9 years ago

Yes, we should be doing this. One wrinkle: legends are specified per style, and unless there's only one style or there is a style named "default", we have no idea which style we're getting when we don't specify one. The WMS spec explicitly says you can't count on the first style being the default one, so which one is the actual default is apparently an unspecified server-side choice. Ugh.

kring commented 9 years ago

WMS 1.3.0 spec section 7.3.3.4:

If the server advertises several styles for a layer, and the client sends a request for the default style, the choice of which style to use as default is at the discretion of the server. The ordering of styles in the service metadata does not indicate which is the default

kring commented 9 years ago

I love that OGC recognized that users might want to know which style is the default, and then left us with no way to determine it. :)

meh9 commented 9 years ago

Currently we make up our own legendUrl if none is specified in the init file. In many cases, particularly for GA, this means we get a cut off legend since their ArcGIS WMS implementation has a too narrow default width. In many cases they are therefore specifying a custom made static PNG in the GetCapabilities LegendURL, which we always do not get. They are legitimately asking why we are not using their custom legends.

We could specify a custom legendUrl in the init file for the layer, but this doesn't work for wms-GetCapabilities groups since it doesn't make sense to have a single legendUrl specified in an itemProperties block as it would not be the correct legend for all layers in the group.

Doesn't it make more sense to arbitrarily pick the first LegendURL in the GetCapabilities for a layer and display that, as that would cover the majority of cases, including dynamic groups. For the cases where we then get the incorrect styling because OGC has no way to determine what style legend to use, we can specify a specific legendUrl in the init file? Ignoring the LegendURL in the GetCapabilities in favour of making up our own just doesn't seem like the right thing to do.

kring commented 9 years ago

Mostly I agree, but here are a couple of thoughts on this:

In many cases they are therefore specifying a custom made static PNG in the GetCapabilities LegendURL, which we always do not get. They are legitimately asking why we are not using their custom legends.

In NM, at least, we're accessing most of the GA ArcGIS services via the Esri REST interfaces rather than via WMS. Sadly the REST interfaces don't have any way to expose a custom legend. That's why NM currently includes the custom legend URLs in the init file instead.

Ignoring the LegendURL in the GetCapabilities in favour of making up our own just doesn't seem like the right thing to do.

This is a very unfair characterization. We're not "making up our own", we're invoking the GetLegendGraphic service, following the WMS spec's description of how to do so. The WMS spec places no requirement on what sort of image needs to be returned from that service (other than meeting the requirements specified in the URL, but that doesn't constrain things much in our case), so in a perfect world the GA-defined custom legends would be returned from that service. Unfortunately that isn't happening, likely because the Esri server doesn't provide any way to do so. This, by the way, is the reason we generally use the Esri-native interfaces when talking to an Esri server: Esri's WMS implementation is not exactly thorough.

Eventually we will have code that generates nice looking legends using the Esri interfaces, because they provide rich metadata. For example: http://www.ga.gov.au/gis/rest/services/topography/Dynamic_National_Map_Elevation_Relief_and_Physiography/MapServer/legend?f=pjson

Anyway, given that this is the world we live in, I agree that just using the legend associated with the first style (at least as an option and probably as the default) is a reasonable thing to do, despite the WMS spec explicitly saying that doing so will NOT be reliable.

meh9 commented 9 years ago

I apologise for the wording, I certainly didn't mean to be harsh about the way things are currently being done, I merely meant to point out that what Terria does at the moment is not ideal for how we use it.

rsignell-usgs commented 8 years ago

One more issue is that when using TerriaJS to access WMS from dynamically-generated servers like ncWMS and sci-wms, the COLORSCALERANGE limits specified by the user are not being displayed on the legend (see for example, https://github.com/TerriaJS/terriajs/issues/774#issuecomment-114441931).

The terriaJS request looks like: http://thredds.ucar.edu/thredds/wms/grib/NCEP/WW3/Global/Best?service=WMS&version=1.3.0&request=GetLegendGraphic&format=image/png&layer=Significant_height_of_combined_wind_waves_and_swell_surface

While I see that godiva2 is being sneaky. It uses a non-standard COLORBARONLY parameter: http://thredds.ucar.edu/thredds/wms/grib/NCEP/WW3/Global/Best?REQUEST=GetLegendGraphic&COLORBARONLY=true&WIDTH=1&HEIGHT=398&PALETTE=rainbow&NUMCOLORBANDS=20 and then uses the color limits supplied by the user to label the legend, like this: 2015-11-07_0759 This is actually pretty smart. It allows a nice, intuitive way for the user to specify the COLORRANGESCALE limits as well!

The legend window of TerrisJS (e.g. below) is perfectly set up for this approach, so implementing the ability to specify the limits (for those WMS servers that support COLORSCALERANGE) would kill two birds with one stone, solving this issue as well https://github.com/TerriaJS/terriajs/issues/774#issuecomment-114441931

6-23-2015 6-46-01 am

AlexGilleran commented 8 years ago

@meh9 is there a current example of a WMS dataset with a bad image using the current solution that will be improved by getting the legend from LegendURL so I can verify my solution? Transmission lines now apparently use ArcGis and have no legend image specified.

meh9 commented 8 years ago

Many Geoscience Australia layers all have custom legends, like the WMS implementation of the Transmission Lines:

http://www.ga.gov.au/gis/services/topography/National_Electricity_Transmission_Lines/MapServer/WMSServer?request=GetCapabilities&service=WMS

Also Land Tenure:

http://services.ga.gov.au/gis/services/Northern_Australia_Land_Tenure/MapServer/WMSServer?request=GetCapabilities&service=WMS

There are many more.

Here is an example of a service that has 2 legend styles, where we should make sure to pick the first one:

http://neii.bom.gov.au/services/solarclim/wms/data/annClim_gloHorExp1Day.nc?service=WMS&version=1.3.0&request=GetCapabilities