Thursday, December 13, 2012

Don't "upgrade" to WMS 1.3.0 unless you really have to, stick to 1.1.1

Chances are that you already heard me say something along the lines of "Don't 'upgrade' to  WMS 1.3.0 unless you really have to because it's a mess, stick to WMS 1.1.1 if you can". This may sound like an old story to those who have been around since the adoption of WMS 1.3.0 in 2004, but believe it or not we still hit those 1.3.0 issues today 8 years later. The last time was a few weeks ago and that got me started on that same old rant once again. I figured that I'd archive a copy of it here once and for all, and next time I can just point people to this blog.

The long story


"Don't 'upgrade' to  WMS 1.3.0 unless you really have to because it's a mess, stick to WMS 1.1.1 if you can"... well, I may not have used those exact words, but I mean it, WMS 1.3.0 is a pain to support properly, both on the client and on the server side, and should be avoided unless you have very good reasons to switch to it, like requirement for ISO compliance for instance. If you can stick to WMS 1.1.1 then you will be much happier.

I was involved with the OGC revision working group (RWG) that worked on the adoption of WMS 1.3.0 and I had the "chance" (or not?) to witness what happened. The "problem" is that OGC was trying to get WMS 1.3.0 approved as an ISO spec, and the ISO review process forced them to break compatibility with WMS 1.1.1 and older on a few aspects in order to meet the very strict ISO requirements.

One of those aspects was a requirement to honour the axis order defined by EPSG in its database of coordinate systems. In WMS 1.1.1 and older, early day OGC WMS authors and implementers had made a "mistake" and always assumed an x-followed-by-y axis order for coordinates, so the BBOX for EPSG:4326 (WGS84 geographic coordinates in degrees) was treated as:

  BBOX=lon_min, lat_min, lon_max, lat_max

But the EPSG database that WMS refers to defines the axis order for its 4326 SRS to be latitude followed by longitude (or y-x for the mathematicians around the table), so in WMS 1.3.0, you have to use:

  BBOX=lat_min, lon_min, lat_max, lon_max

However, for most projected coordinate systems, EPSG still defines the axis order as x followed by y, so nothing changes between 1.1.1 and 1.3.0 in those cases. For instance, with EPSG:3857 (Google Mercator projection in meters), the BBOX coordinate order remains the same for both WMS 1.1.1 and 1.3.0:

  BBOX=xmin, ymin, xmax, ymax

This strict compliance requirement imposed by the ISO review process on the OGC RWG means that WMS 1.3.0 server and client code needs to be aware of the axis order for each SRS that it supports and to use the correct coordinate order in its BBOX (and also the BoundingBox elements of the GetCapabilities output IIRC)... that's the mess I was alluding to. (There are a few thousand codes in the EPSG database that software needs to be made aware of.)

The issues that we encounter the most often with WMS 1.3.0 implementation range from incomplete axis order support for some EPSG codes to some implementations incorrectly assuming that WMS 1.3.0 just swaps the axis order to y-x for every SRS. And yes, there are still some implementations in 2012 that don't get this right.

Note that to help work around this issue for those writing simple clients/servers who want to avoid using EPSG codes and be free to continue with x-y axis order everywhere, the WMS 1.3.0 RWG invented a new "CRS:*" namespace for projection codes in which it defined a few well-known coordinate systems. They are listed in Annex B of the WMS 1.3.0 spec. The most common one is CRS:84 which is essentially EPSG:4326 with lon-lat (x-y) axis ordering. Unfortunately this is just a patch and doesn't address the core issue which is a brutal incompatibility between WMS 1.1.1 and 1.3.0.



Since MapServer complies with all those requirements, here are some example showing the change in behaviors between WMS 1.1.1 and 1.3.0 with MapServer WMS, taking the following BBOX:


Using WMS 1.3.0 with EPSG:4326 (with lat-lon, a.k.a y-x axis order):


this bbox is interpreted as

  lat_min = 90 South 
  lon_min = 0
  lat_max = 0
  lon_max = 90 East

and you get the following map image:

 However, if you want to keep it simple and stick to x-y axis ordering, and want the BBOX treated as

  lon_min = 90 West
  lat_min = 0 
  lon_max = 0
  lat_max = 90 North

then you can either use WMS 1.3.0 with CRS:84:


Or stick to WMS 1.1.1 with EPSG:4326:


and in both cases you'll get this:

Hopefully now you'll understand next time you hear me mumble "... stick to WMS 1.1.1...".

P.S. Also note in the examples above that the WMS 1.1.1 "srs=..." parameter was renamed to "crs=..." in WMS 1.3.0, but that's a story for another day.