How can I get latitude, longitude from x, y on a Mercator map (JPEG)?

latitude-longitude, mapping, maps, math

Solution

Here is some code for you... Let me know if you need more explanation.

    /// <summary>
    /// Calculates the Y-value (inverse Gudermannian function) for a latitude. 
    /// <para><see cref="http://en.wikipedia.org/wiki/Gudermannian_function"/></para>
    /// </summary>
    /// <param name="latitude">The latitude in degrees to use for calculating the Y-value.</param>
    /// <returns>The Y-value for the given latitude.</returns>
    public static double GudermannianInv(double latitude)
    {
        double sign = Math.Sign(latitude);
        double sin = Math.Sin(latitude * RADIANS_PER_DEGREE * sign);
        return sign * (Math.Log((1.0 + sin) / (1.0 - sin)) / 2.0);
    }

    /// <summary>
    /// Returns the Latitude in degrees for a given Y.
    /// </summary>
    /// <param name="y">Y is in the range of +PI to -PI.</param>
    /// <returns>Latitude in degrees.</returns>
    public static double Gudermannian(double y)
    {
        return Math.Atan(Math.Sinh(y)) * DEGREES_PER_RADIAN;
    }

Problem

I have a Mercator projection map as a JPEG and I would like to know how to relate a given x, y coordinate to its latitude and longitude. I've looked at the Gudermannian function but I honestly don't understand how to take that function and apply it. Namely, what input is it expecting? The implementation I found (JavaScript) seems to take a range between -PI and PI, but what's the correlation between my y-value in pixels and that range? Also, I found this function which takes a latitude and returns the tile for Google Maps, which also uses Mercator. It would seem that if I knew how to inverse this function, I'd be pretty close to having my answer. ``` /*<summary>Get the vertical tile number from a latitude using Mercator projection formula</summary>*/ private int getMercatorLatitude(double lati) { double maxlat = Math.PI; double lat = lati; if (lat > 90) lat = lat - 180; if (lat < -90) lat = lat + 180; // conversion degre=>radians double phi = Math.PI * lat / 180; double res; //double temp = Math.Tan(Math.PI / 4 - phi / 2); //res = Math.Log(temp); res = 0.5 * Math.Log((1 + Math.Sin(phi)) / (1 - Math.Sin(phi))); double maxTileY = Math.Pow(2, zoom); int result = (int)(((1 - res / maxlat) / 2) * (maxTileY)); return (result); } ```

Original source

Related problems