EPSG Problems


EPSG:54004 problem fig 1
Fig 1 – Something is not right with DIA?

Life is full of problems. With eight kids we have lots of problems, especially as school gets started up again. Life in the chaos lane has its moments, but the problem that has been baffling me this week has to do with EPSG coordinate systems and in particular the venerable but unofficial EPSG:54004.

EPSG:54004 is really not official. You won’t find it in the official EPSG registry. It is commonly used, however, ever since it was added as a “user extension” by Google, originally for use in Google maps.

Here are the basics of EPSG:54004

PROJCS["World_Mercator",
    GEOGCS["GCS_WGS_1984",
        DATUM["WGS_1984",
            SPHEROID["WGS_1984",6378137,298.257223563]],
        PRIMEM["Greenwich",0],
        UNIT["Degree",0.017453292519943295]],
    PROJECTION["Mercator_1SP"],
    PARAMETER["False_Easting",0],
    PARAMETER["False_Northing",0],
    PARAMETER["Central_Meridian",0],
    PARAMETER["Standard_Parallel_1",0],
    UNIT["Meter",1],
    AUTHORITY["EPSG","54004"]]
It is similar to EPSG:900913

PROJCS["Google Mercator",
    GEOGCS["WGS 84",
        DATUM["World Geodetic System 1984",
            SPHEROID["WGS 84",6378137.0,298.257223563,
                AUTHORITY["EPSG","7030"]],
            AUTHORITY["EPSG","6326"]],
        PRIMEM["Greenwich",0.0,
            AUTHORITY["EPSG","8901"]],
        UNIT["degree",0.017453292519943295],
        AXIS["Geodetic latitude",NORTH],
        AXIS["Geodetic longitude",EAST],
        AUTHORITY["EPSG","4326"]],
    PROJECTION["Mercator_1SP"],
    PARAMETER["semi_minor",6378137.0],
    PARAMETER["latitude_of_origin",0.0],
    PARAMETER["central_meridian",0.0],
    PARAMETER["scale_factor",1.0],
    PARAMETER["false_easting",0.0],
    PARAMETER["false_northing",0.0],
    UNIT["m",1.0],
    AXIS["Easting",EAST],
    AXIS["Northing",NORTH],
    AUTHORITY["EPSG","900913"]]

And both are similar to the official, official EPSG:3857

They should be equivalent. All are using earth radius 6378137.0m with a spherical mercator approximation that happens to be very efficient for quad tree tile pyramids. It has been so successful that it’s used in all the online map services, Google, Bing, Yahoo, and Open Street Map. It is also pretty simple to convert latitude, longitude into spherical Mercator coordinates. Using my dog eared John Snyder’s Manual I get something like this:

private Point Mercator(double lon, double lat)
{

        /* spherical mercator for Google, Bing, Yahoo
        * epsg:900913, epsg:54004, epsg:3857 R= 6378137
        * x = longitude
        * y= R*ln(tan(pi/4 +latitude/2)
        */············

        double R = 6378137.0;
        double x = R * Math.PI / 180 * lon;
        double y = R * Math.Log(Math.Tan(Math.PI / 180 *
         (45 + lat / 2.0)));
        return new Point(x, y);
}

The Problem

Now on to the problem, apparently not all EPSG:54004s are equal?

Looking at the screen shot above you can see that the MRLC NLCD 2001 impervious Surface layer using EPSG:54004 shows DIA a few miles south of the Bing Maps DIA? Bing Maps, as noted above, uses the EPSG:3857 spherical mercator which should be the same, but apparently is not? A quick check against OSM and Yahoo base maps verifies the same discrepancy.

I’ve been known to get tangled up in coordinate systems, so just as a sanity check here is a screenshot with DRCOG’s Network layer also rendered as EPSG:54004:

EPSG:54004 problem fig 2
Fig 2 – DRCOG EPSG:54004 looks right with Bing Maps but wrong with MRLC?

The DRCOG EPSG:54004 and Bing Maps align correctly so it is now 2 to 1 against the MRLC EPSG:54004. But what is going on here?

Taking a peek at DRCOG’s GetCapabilities I can see it is served out of GeoServer. “http://gis.drcog.org:80/geoserver/wms” Here is the user epsg section of GeoServer’s epsg.properties file from my local copy of GeoServer:

54004=PROJCS["WGS84 / Simple Mercator", GEOGCS["WGS 84", DATUM["WGS_1984",
SPHEROID["WGS_1984", 6378137.0, 298.257223563]],
PRIMEM["Greenwich", 0.0], UNIT["degree", 0.017453292519943295]],
PROJECTION["Mercator_1SP_Google"],
PARAMETER["latitude_of_origin", 0.0],
PARAMETER["central_meridian", 0.0],
PARAMETER["scale_factor", 1.0],
PARAMETER["false_easting", 0.0],
PARAMETER["false_northing", 0.0], UNIT["m", 1.0],
AXIS["x", EAST], AXIS["y", NORTH], AUTHORITY["EPSG","54004"]]

It looks familiar.

The MRLC GetCapabilites shows an ESRI server,
“http://ims.cr.usgs.gov:80/wmsconnector/com.esri.wms.Esrimap.”
Perhaps this is a clue. I know of several other ESRI WMS services so going to the National Atlas, I can see, yes, it publishes an EPSG:54004 SRS: <SRS>EPSG:54004</SRS>

I plug the National Atlas into my handy WMSClient and take a look. I selected the major highways and interstates which are visible, with opacity turned up, against the Impervious Surface backdrop. You can see a high degree of correlation between the two layers, and both are no where near the Bing base map?

EPSG:54004 problem fig 3
Fig 3 – National Atlas EPSG:54004 agrees with impervious surface?

OK, now it’s 2 to 2 and the end of the ninth. I am clear that the EPSG:54004 discrepancy has something to do with a difference in interpretation between WMS servers. It appears that ESRI is consistently different from Bing Maps and GeoServer. ESRI is the expert in this area, so my thought is there may be some unusual EPSG consideration that ESRI has caught and others possibly have not.

A bit of Googling brings up an older ESRI technical article that may have some bearing. However, nothing very clear about this large of a discrepancy. Going with a hunch I tried pretending ESRI EPSG:54004 was ellipsoidal rather than spherically based. Doing a quick switch to an Ellipsoidal Mercator calculation, however, makes no discernable difference.

private Point MercatorEllipsoid(double lon, double lat)
{
        double a = 6378137.0;// meters equitorial radius            
        double e = 1 / 298.257223563;
        double ctrmerid = 0.0;

        double px = lon * Math.PI / 180;
        double py = lat * Math.PI / 180;
        double pc = ctrmerid * Math.PI / 180;

        double x = a * (px - pc);
        double y = a * (Math.Log(Math.Tan((45.0 * Math.PI / 180) + py / 2.0)
        * Math.Pow((1.0 - e * Math.Sin(py))
        / (1.0 + e * Math.Sin(py)), e / 2.0)));
        return new Point(x, y);

}

Switching to the universal EPSG:4326 lined things up well enough. Unfortunately it does nothing to solve the mystery.

EPSG:4326  fig 3
Fig 4 – Switching to EPSG:4326 brings layers into alignment at this zoom level

Summary

Mystery is not resolved. If others have some insight, I’d like to hear it, especially from experts with ESRI com.esri.wms.Esrimap experience. If anyone wants to play with these EPSG:54004 layers I have a simple WMS client here: Silverlight WMSClient.

6 Responses to “EPSG Problems”

  1. bFlood says:

    thats a pretty large offset so I’m not sure if this will help but ESRI servers usually change the requested bbox to match the aspect ratio of the image by default. This has been a problem aligning WMS to GM/VE/etc in the past so you could try to append reaspect=false to your WMS request url

    cheers
    brian

  2. dnewcomb says:

    Have you tried other WMS clients like UDig or QGIS to ensure it’s not the WMS client?

  3. Randy says:

    Hi Brian,

    Brian Timoney passed on your suggestion as well. I tried it but no change.

    Hi dnewcomb,

    I looked at this in uDig but it’s hard for me to see what the actual WMS url call is, so I can’t tell whether uDig is warping after the image request (as 4326) or not. I also noted uDig doesn’t seem to have 54004 in their list as of 1.1.1. Also missing are 900913 and 3857(does substitute AGD66(EPSG:4202)). The only spherical mercator I could try was 41001, which isn’t published in the GetCapabilities and resulted in similar discrepancy.
    Of course 4326 does align as you zoom in to closer levels.

    Also tried Glbal Mapper but I couldn’t make it use 54004?

    Still baffled. I guess the problem is really that EPSG:3857 is so rare and these other partly supported spherical mercators 41001, 900913, 54004 are not consistently published by WMS servers or consumed by WMS clients. The best solution would be for EPSG:3857 to be universally adopted.

  4. sharpgis says:

    First of all, there is no such thing as “EPSG:900913″. When you put EPSG in front of it, it says that this is defined by EPSG. This is not the case. It was a number coined by a blog, because it looks like it says “google” (never mind the fact that Virtual Earth was the first ones to use this, not Google).

    Second, 54004 was never meant to be the same as 3857. The reason is that they are using different datums. You need to define a datum transform to go from one to the other to get your transformations to look right. The error you are seeing is exactly the expected error for a datum transform error.
    Here’s the main difference between the two spatial references:
    54004: DATUM["WGS_1984", SPHEROID["WGS_1984",6378137,298.257223563]]
    3857: DATUM["WGS_1984_SPHERE", SPHEROID["WGS_1984",6378137,0]]
    The ‘e’ value in your formula above is therefore also wrong, since a sphere has no flattening. It does work for 54004 since this one defines a flattening. The conversion is actually a lot simpler because of the lack of flattening as described here: http://cfis.savagexi.com/2006/05/03/google-maps-deconstructed

    Here’s a couple of others links that might also help you:
    http://www.sharpgis.net/post/2007/07/27/The-Microsoft-Live-Maps-and-Google-Maps-projection.aspx
    http://www.sharpgis.net/post/2008/05/15/SphericalWeb-Mercator-EPSG-code-3785.aspx
    http://www.sharpgis.net/post/2007/05/05/Spatial-references2c-coordinate-systems2c-projections2c-datums2c-ellipsoids-e28093-confusing.aspx

    If you are using ESRI software, use WKID 102113, since this was the ID ESRI chose before EPSG finally defined one.

  5. Randy says:

    Hi is it Morten,

    Thanks for the input.

    Yes there is no such thing as EPSG:900913 or 54004, or 41001, only EPSG:3857. Unfortunately the EPSG prefix seems to get used in various tools out there. Probably shouldn’t reference them that way, but I think it can’t be helped by this time.

    Interesting, I thought that 900913 was around before Virtual Earth showed up. It does seem to be fairly commonly referenced as “900913=PROJCS[”WGS84 / Google Mercator, …”
    I thought EPSG:3785 was sponsored by Microsoft and then it was deprecated in favor of EPSG:3857. I could be wrong on that.

    I’m not sure what formula you are refering to above. The Mercator() uses spherical with no eccentricity, MercatorEllipsoid does/should use e since it was an attempt to see whether the datum diff noted would account for the shift. It didn’t seem to? It is used to calculate the BBOX coordinates for the GetMap requests.

    Apparently GeoServers 54004 def is different from the ESRI def in some way since they give different results? GeoServers’s matches OSM, Yahoo etc, ESRI’s doesn’t.

    When I get a chance I’ll look into it more. I want to change things a bit in my client so I can choose EPSG for each of the services independently and look at match ups.

    thanks
    randy

  6. Randy says:

    Hurray! found the problem!

    Thanks to SharpGIS. Morten’s input got me looking in the right direction!

    My orginal hunch was correct it was the ellipsoid datum vs spherical.

    However, I finally realized I had made a big error on the eccentricity. Don’t know what I was thinking at the time but e should be:
    double f = 1 / 298.257223563;
    e = Math.Sqrt(2*f – Math.Pow(f,2));
    or
    e = 0.081819190842621486;

    Use that in MercatorEllipsoid for com.esri.wms.Esrimap services and it all comes together correctly.

    So GeoServer must ignore the flattening 298.257223563 or else assume it is like the 900913 where flattening is overridden by making semi_minor axis = major.
    PARAMETER["semi_minor",6378137.0]

    At any rate I now must check to see if ESRI is providing the WMS or some other service and take into account datum difference between EPSG:3857 and ESRI:54004

    thanks
    randy

Leave a Reply

You must be logged in to post a comment.