GeoLatte / geolatte-geom

A geometry model that conforms to the OGC Simple Features for SQL specification.
Other
134 stars 63 forks source link

Problem converting from EPSG:32634 to EPSG:4326 #127

Open samodadela opened 3 years ago

samodadela commented 3 years ago

I'm trying to convert some (C2D, cartesian, northing/easting) coordinates from EPSG:32634 to EPSG:4326 (G2D, geographic, long/lat). Here's the test I took for reference:

    @Test
    public void testLambert72toWGS84() {
        final ProjectedCoordinateReferenceSystem C2D_EPSG_SRC =
                CrsRegistry.getProjectedCoordinateReferenceSystemForEPSG(31370);
        final Geographic2DCoordinateReferenceSystem G2D_EPSG_TGT =
                CrsRegistry.getGeographicCoordinateReferenceSystemForEPSG(4326);

        CrsId srcCrsId = C2D_EPSG_SRC.getCrsId();
        CrsId tgtCrsId = G2D_EPSG_TGT.getCrsId();
        CoordinateOperation operation = CoordinateOperations.transform(srcCrsId, tgtCrsId);

        double[] in = new double[]{250_000, 125_000};
        double[] out = new double[2];
        operation.forward(in, out);
        assertEquals(5.77620918429282, out[0], .0001);
        assertEquals(50.4273341669192, out[1], .0001);
    }

This test coverts from 31370 to 4326 and works as expected.

I modified the test to take in 32634 instead of 31370 and changed the in coordinates:

    @Test
    public void testUTM34toWGS84() {
        final ProjectedCoordinateReferenceSystem C2D_EPSG_SRC =
                CrsRegistry.getProjectedCoordinateReferenceSystemForEPSG(32634);
        final Geographic2DCoordinateReferenceSystem G2D_EPSG_TGT =
                CrsRegistry.getGeographicCoordinateReferenceSystemForEPSG(4326);

        CrsId srcCrsId = C2D_EPSG_SRC.getCrsId();
        CrsId tgtCrsId = G2D_EPSG_TGT.getCrsId();
        CoordinateOperation operation = CoordinateOperations.transform(srcCrsId, tgtCrsId);

        // EPSG:32634, WGS 84 / UTM zone 34N
        // https://epsg.io/32634
        // Center: 500000.00 4649776.22
        double[] in = new double[]{500000.00, 4649776.22};
        // double[] in = new double[]{4649776.2, 2500000.00};
        double[] out = new double[2];
        operation.forward(in, out);
        assertEquals(5.77620918429282, out[0], .0001); // todo: change to real values
        assertEquals(50.4273341669192, out[1], .0001); // todo: change to real values
    }

Of course the values in the assertEquals are wrong for my case... When I run the test, though, I get this error: org.opentest4j.AssertionFailedError: Expected :5.77620918429282 Actual :500000.0

Which means that operation.forward() converted in[0] to 500000.0 - it just copied in[0] to out[0]... and out should be specified in degrees (lat/long).

I'm probably doing something wrong.. but can't spot the problem.

I tried this with geolatte-geom 1.6.0 and 1.8.0.

maesenka commented 3 years ago

The transformation you need is not yet supported. You should have received some sort of error, rather than an incorrect answer. And I really should have documented what works. Sorry, about that.

This package is very much a work in progress, with currently only the lambert72 (I work in Belgium), WGS84 and Web Mercator supported.

If you can wait a bit, I can try to add the UTM transformation

samodadela commented 3 years ago

Sure, I can wait and thank you very much for your help. I really couldn't have figured it out myself - stepping through the code it seemed like it was trying to do the conversion.

negesti commented 2 years ago

@maesenka i would need a UTM tranformer too. Can you give me some hints how I could add one? Edit: Looks like org.geotools support the transformation and can be used in combination with geolatte

maesenka commented 2 years ago

The model for projection systems is based on the EPSG database. It has a lot of good documentation in the Guidance notes on how to implement coordinate operations, transformations, etc.

For UTM you need to implement a org.geolatte.geom.crs.trans.CoordinateOperation for Transverse Mercator in the package o.g.g.crs.trans.projections.

For an example see the LambertConformalConic2SP implementation, and its unit test LambertCC2SPTest. The test cases come either from the EPSG database, or are generated using the st_transform() function in Postgis.

michikommader commented 3 months ago

The transformation you need is not yet supported. You should have received some sort of error, rather than an incorrect answer.

Yes, the documentation lacks a usage guidance. Just from looking at the Javadoc I expected that calling CoordinateOperations.transform(sourceCrs, targetCrs) would define an operation which would transform my WGS 84 coordinates to projected UTM coordinates. The returned CoordinateOperation is usable though but results in "identity transformation" without any significant value changes. That made me wonder for quite a long time until I found this thread. Some kind of error or warning that the actual transformation is undefined would have been nice.

What I find confusing is that the actual coordinate systems are well-defined in thorough detail etc. and also exist when querying the CrsRegistry with an EPSG code but the underlying transformation functions between those are not implemented.