locationtech / proj4j

Java port of the Proj.4 library for coordinate reprojection
Other
184 stars 73 forks source link

Invalid conversion EPSG:5514 - JTSK #25

Closed jandam closed 3 years ago

jandam commented 5 years ago

I get wrong result for EPSG:5514 - JTSK specified by proj4j parameters. Conversion WGS84 -> JTSK is almost correct except SIGNs. Conversion from JTSK -> WGS84 is WRONG.

JTSK : ProjCoordinate[747963.6497538437 1041493.3287851878 NaN] // negative signs WGS84: ProjCoordinate[24.834517978270924 -59.948074516468246 NaN] // - wrong should be: 14.346996204306555,50.09465901453681

Values and code example is derived from JavaScript: http://jsfiddle.net/xiceph/79QHW/1/

https://github.com/proj4js/proj4js/issues/115

    private static final CoordinateTransformFactory ctFactory = new CoordinateTransformFactory();
    private static final String JTSK_PARAM_5514 = "+title=Krovak +proj=krovak +lat_0=49.5 +lon_0=24.83333333333333 +alpha=30.28813972222222 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +units=m +towgs84=570.8,85.7,462.8,4.998,1.587,5.261,3.56 +no_defs";
    private static final CoordinateReferenceSystem WGS84 = new CRSFactory().createFromName("epsg:4326");
    private static final CoordinateReferenceSystem JTSK_5514 = new CRSFactory().createFromParameters("JTSK", JTSK_PARAM_5514);

    public static void main(final String[] args) {
        CoordinateTransform transFromWGS84 = ctFactory.createTransform(WGS84, JTSK_5514);
        CoordinateTransform transToWGS84 = ctFactory.createTransform(JTSK_5514, WGS84);
        ProjCoordinate pout = new ProjCoordinate();
        ProjCoordinate srcWGS84 = new ProjCoordinate( 14.346996204306555,50.09465901453681);
        System.out.println("JTSK : " + transFromWGS84.transform(srcWGS84, pout));
        pout = new ProjCoordinate( -747963.64999999851, -1041493.3299999982);
        System.out.println("WGS84: " + transToWGS84.transform(pout, new ProjCoordinate()));
}
jandam commented 5 years ago

Maybe same issue as in other projects https://github.com/OSGeo/proj.4/issues/233

https://github.com/OpenOrienteering/mapper/issues/542

karol-bujacek commented 3 years ago

I’ve also encountered problems with EPSG:5514. I am not so experienced in this field, so I might be wrong and the problem might lie in my code, but I’ve checked other two tools and the result is different than result from Proj4J.

I need to convert from EPSG:4326 to EPSG:5514. According to page https://epsg.io/5514, coordinates should be negative. Using the transform tool on the same page, https://epsg.io/transform#s_srs=4326&t_srs=5514&x=16.6000000&y=49.1900000, I got negative numbers -598803.96 and -1161258.17.

Using the cs2cs command line tool, Rel. 6.3.1, February 10th, 2020, I got result with negative numbers:

~ echo 16.606451133 49.193040494 | cs2cs  +init=epsg:4326 +to +init=epsg:5514 
-598298.71  -1160969.65 0.00

(installed as deb package, https://proj.org/install.html#debian)

However, Proj4J gives different results. This is test code and log output is below.

import org.junit.Before;
import org.junit.Test;
import org.locationtech.proj4j.CRSFactory;
import org.locationtech.proj4j.CoordinateTransform;
import org.locationtech.proj4j.CoordinateTransformFactory;
import org.locationtech.proj4j.ProjCoordinate;

import static org.junit.Assert.assertEquals;

public class TransformTest {
    private  ProjCoordinate toCoordinate;

    @Before
    public void doTransform() {
        final String coordinateSystemFrom = "epsg:4326";
        final String coordinateSystemTo = "epsg:5514";

        CoordinateTransformFactory coordinateTransformFactory = new CoordinateTransformFactory();
        CRSFactory csFactory = new CRSFactory();

        CoordinateTransform transform = coordinateTransformFactory.createTransform(
                csFactory.createFromName(coordinateSystemFrom),
                csFactory.createFromName(coordinateSystemTo)
        );

        ProjCoordinate fromCoordinate = new ProjCoordinate(16.6064512, 49.1930405);
        toCoordinate = new ProjCoordinate();
        transform.transform(fromCoordinate, toCoordinate);
    }

    @Test
    public void test_x() {
        assertEquals(-598298.71, toCoordinate.x, 1);
    }

    @Test
    public void test_y() {
        assertEquals(-1160969.65, toCoordinate.y, 1);
    }
}

From the log:

java.lang.AssertionError: 
Expected :-598298.71
Actual   :598300.1459260784
java.lang.AssertionError: 
Expected :-1160969.65
Actual   :1160972.570532075
karol-bujacek commented 3 years ago

The abovementioned test is working if I use this as a second parameter for coordinateTransformFactory.createTransform:

        String paramStr = "+proj=krovak +lat_0=49.5 +lon_0=24.83333333333333 " +
                "+alpha=30.28813972222222 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +pm=greenwich" +
                "+units=m +no_defs +towgs84=570.8,85.7,462.8,4.998,1.587,5.261,3.56 +axis=wsu";

        CoordinateTransform transform = coordinateTransformFactory.createTransform(
                csFactory.createFromName(coordinateSystemFrom),
                csFactory.createFromParameters("5514", paramStr)
        );

This param string is copied from comment https://github.com/OSGeo/PROJ/issues/233#issuecomment-158810753 and +axis=wsu is used, as https://github.com/OSGeo/PROJ/issues/233#issuecomment-158977854 suggested. The value wsu is taken from the proj documentation https://proj.org/usage/projections.html#axis-orientation.

After this change these two tests are passing.

However, I am not sure if the fix can be ‘so easy’. As I stated in my previous comment, I am quite new in this field without solid knowledge (I am not deeply involved into GIS, I just need to do some simple transformations in my application) and I might overlook some unwanted side effects.

karol-bujacek commented 3 years ago

And by the way, I am using Proj4J version 1.1.1.