'Converting coordinates from EPSG 3857 to 4326

I have in my DB a list of coordinates in EPSG 3857 format. I need to convert them in EPSG 4326 I'm trying to use DotSpatial but my code always retun a double array of Infinity.

public double[] ConvertCoodinates()
    {
        double[] xy = new double[2];
        xy[0] = 5085240.8300000000;
        xy[1] = 1530088.9600000000;
    //An array for the z coordinate
        double[] z = new double[1];
        z[0] = 0;
        ProjectionInfo pStart = KnownCoordinateSystems.Geographic.World.WGS1984;
        pStart.AuthorityCode = 3857;
        ProjectionInfo pEnd = KnownCoordinateSystems.Geographic.World.WGS1984;
        pEnd.AuthorityCode = 4326;
        Reproject.ReprojectPoints(xy, z, pStart, pEnd, 0, 1);
        return xy;
    }

The xy array always cointain infinity; Can someone help me?



Solution 1:[1]

It is a bit tricky to project EPSG 3857 coordinates to EPSG 4326 coordinate system. Microsoft recommends using ProjNet4GeoAPI so I decided to use that.

https://docs.microsoft.com/en-us/ef/core/modeling/spatial#srid-ignored-during-client-operations

I have verified that it works here:

http://epsg.io/transform#s_srs=3857&t_srs=4326&x=1530088.9600000&y=5085240.8300000

Example conversion:

var x = 1530088.96d;
var y = 5085240.83d;

var epsg3857ProjectedCoordinateSystem = ProjNet.CoordinateSystems.ProjectedCoordinateSystem.WebMercator;
var epsg4326GeographicCoordinateSystem = ProjNet.CoordinateSystems.GeographicCoordinateSystem.WGS84;

var coordinateTransformationFactory = new ProjNet.CoordinateSystems.Transformations.CoordinateTransformationFactory();
var coordinateTransformation = coordinateTransformationFactory.CreateFromCoordinateSystems(epsg3857ProjectedCoordinateSystem, epsg4326GeographicCoordinateSystem);

var epsg3857Coordinate = new GeoAPI.Geometries.Coordinate(x, y);

var epsg4326Coordinate = coordinateTransformation.MathTransform.Transform(epsg3857Coordinate);

Solution 2:[2]

It seems there is a mistake in the Javascript version of the selected answer... It always gives me a 2 times bigger answer than it really should, so I ended up diving by 360 instead of 180 (but I admit the Math here are beyond my field of expertise).

Here is the working code :

  coord3857To4326(coord) {
    
    const e_value = 2.7182818284;
    const X = 20037508.34;
    
    const lat3857 = coord.lat
    const long3857 = coord.lng;
    
    //converting the longitute from epsg 3857 to 4326
    const long4326 = (long3857*180)/X;
    
    //converting the latitude from epsg 3857 to 4326 split in multiple lines for readability        
    let lat4326 = lat3857/(X / 180);
    const exponent = (Math.PI / 180) * lat4326;
    
    lat4326 = Math.atan(Math.pow(e_value, exponent));
    lat4326 = lat4326 / (Math.PI / 360); // Here is the fixed line
    lat4326 = lat4326 - 90;

    return {lat:lat4326, lng:long4326};
    
}

I also successfully reversed it :

  coord4326To3857(coord) {

    const X = 20037508.34;

    let long3857 = (coord.lng * X) / 180;

    let lat3857 = parseFloat(coord.lat) + 90;
    lat3857 = lat3857 * (Math.PI/360);
    lat3857 = Math.tan(lat3857);
    lat3857 = Math.log(lat3857);
    lat3857 = lat3857 / (Math.PI / 180);
    
    lat3857 = (lat3857 * X) / 180;

    return {lat:lat3857, lng:long3857};
}

Hope this will help others !

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ogglas
Solution 2