I'm having issues with Geotools reversing the latitude and longitude, using JTS.transform(). It's been driving me mad now for days.
I have different data sets defined in different projections. The goal is that I can map any coordinate in a given projection WKT to a (lon, lat) in WGS84. Here's my util that does the conversion:
public class TransformUtil {
private static CoordinateReferenceSystem wgs;
static {
wgs = DefaultGeographicCRS.WGS84;
}
private static double[] convert(String wkt, double x, double y) throws TransformException {
CoordinateReferenceSystem sourceCRS = CRS.parseWKT(wkt);
MathTransform transform = CRS.findMathTransform(sourceCRS, WGS, true);
Point point = geometryFactory.createPoint( new Coordinate( x, y ) );
Geometry targetGeometry = JTS.transform( point , transform);
Coordinate coord = targetGeometry.getCoordinate();
return new double[] {coord.x, coord.y};
}
}
and here are my unit tests:
public class TestTransformUtil {
private double lon = 5;
private double lat = 50;
private double margin = 1E-5d;
@Test
public void testWgs() {
String wkt = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]";
double[] res = TransformUtil.toLonLat(lon, lat, wkt);
Assert.assertEquals("Longitude", lon, res[0], margin);
Assert.assertEquals("Latitude", lat, res[1], margin);
}
@Test
public void testLaea() {
double x= 3962799.45096;
double y = 2999718.85316;
String wkt = "PROJCS[\"ETRS89-extended / LAEA Europe\",GEOGCS[\"ETRS89\",DATUM[\"European_Terrestrial_Reference_System_1989\",SPHEROID[\"GRS 1980\",6378137,298.257222101004,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6258\"]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4258\"]],PROJECTION[\"Lambert_Azimuthal_Equal_Area\"],PARAMETER[\"latitude_of_center\",52],PARAMETER[\"longitude_of_center\",10],PARAMETER[\"false_easting\",4321000],PARAMETER[\"false_northing\",3210000],UNIT[\"metre\",1],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]";
double[] res = TransformUtil.toLonLat(x, y, wkt);
Assert.assertEquals("Longitude", lon, res[0], margin);
Assert.assertEquals("Latitude", lat, res[1], margin);
}
}
What happens is really confusing. For the WGS84 to WGS84 projection testWgs(), the transform action reverses the coordinates. Coordinate.x becomes the latitude, Coordinate.y is the longitude, thus the assert fails:
java.lang.AssertionError: Longitude expected:<5.0> but was:<50.0>
The testLaea() passes without problems.
I found this tip in the geotools docs: https://docs.geotools.org/stable/userguide/tutorial/geometry/geometrycrs.html#workarounds that says that you should use
private static CoordinateReferenceSystem wgs;
static {
try {
CRSAuthorityFactory factory = CRS.getAuthorityFactory(true);
wgs = factory.createCoordinateReferenceSystem("urn:ogc:def:crs:EPSG:6.6:4326");
} catch (FactoryException e) {
e.printStackTrace();
}
}
When I run the tests now, testWgs() passes, but now the coordinates are reversed for testLaea()!!
The final thing I tried is to use
static {
System.setProperty("org.geotools.referencing.forceXY", "true");
//wgs = ...
}
which does nothing at all. Can anybody explain what's happing here, and does anyone know how I can force the outcome of the transform always to have x=longitude and y=latitude? Thanks!