Skip to content

Commit 45fa5a1

Browse files
authored
GeocentricConverter equality check after WGS param overrides (#77)
* GeocentricConverter equality check after WGS param overrides * comments, geocentric converter comparisons * newly fixed tests * removed no longer failing test
1 parent 03d3123 commit 45fa5a1

File tree

8 files changed

+61
-36
lines changed

8 files changed

+61
-36
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
### Fixed
1010
- Adjustment to OSGB36 datum transform e.g. EPSG: 27700
11+
- GeocentricConverter equality check after grid shift WGS param override e.g. EPSG: 27700 [#32]
1112
- +nadgrids=@null support e.g. EPSG: 3857
1213

1314
## [1.1.3] - 2021-06-17

src/main/java/org/locationtech/proj4j/BasicCoordinateTransform.java

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,28 +79,45 @@ public BasicCoordinateTransform(CoordinateReferenceSystem srcCRS,
7979
doDatumTransform = doInverseProjection && doForwardProjection
8080
&& srcCRS.getDatum() != tgtCRS.getDatum();
8181

82+
boolean geocentric = false;
83+
8284
if (doDatumTransform) {
8385

8486
boolean isEllipsoidEqual = srcCRS.getDatum().getEllipsoid().isEqual(tgtCRS.getDatum().getEllipsoid());
85-
transformViaGeocentric = ! isEllipsoidEqual || srcCRS.getDatum().hasTransformToWGS84()
87+
geocentric = ! isEllipsoidEqual || srcCRS.getDatum().hasTransformToWGS84()
8688
|| tgtCRS.getDatum().hasTransformToWGS84();
8789

88-
if (transformViaGeocentric) {
90+
if (geocentric) {
8991
srcGeoConv = new GeocentricConverter(srcCRS.getDatum().getEllipsoid());
9092
tgtGeoConv = new GeocentricConverter(tgtCRS.getDatum().getEllipsoid());
9193

92-
if (srcCRS.getDatum().getTransformType() == Datum.TYPE_GRIDSHIFT) {
93-
srcGeoConv.overrideWithWGS84Params();
94-
}
94+
int srcTransformType = srcCRS.getDatum().getTransformType();
95+
int tgtTransformType = tgtCRS.getDatum().getTransformType();
96+
97+
if (srcTransformType == Datum.TYPE_GRIDSHIFT || tgtTransformType == Datum.TYPE_GRIDSHIFT) {
98+
99+
if (srcTransformType == Datum.TYPE_GRIDSHIFT) {
100+
srcGeoConv.overrideWithWGS84Params();
101+
}
102+
103+
if (tgtTransformType == Datum.TYPE_GRIDSHIFT) {
104+
tgtGeoConv.overrideWithWGS84Params();
105+
}
106+
107+
// After WGS84 params override, check if geocentric transform is still required
108+
// https://github.com/OSGeo/PROJ/blob/5.2.0/src/pj_transform.c#L892
109+
if(srcGeoConv.isEqual(tgtGeoConv)) {
110+
geocentric = false;
111+
srcGeoConv = null;
112+
tgtGeoConv = null;
113+
}
95114

96-
if (tgtCRS.getDatum().getTransformType() == Datum.TYPE_GRIDSHIFT) {
97-
tgtGeoConv.overrideWithWGS84Params();
98115
}
99116
}
100117

101-
} else {
102-
transformViaGeocentric=false;
103118
}
119+
120+
transformViaGeocentric = geocentric;
104121
}
105122

106123
@Override
@@ -172,6 +189,10 @@ private void datumTransform(ProjCoordinate pt) {
172189
|| tgtCRS.getDatum().getTransformType() == Datum.TYPE_UNKNOWN)
173190
return;
174191

192+
/* -------------------------------------------------------------------- */
193+
/* If this datum requires grid shifts, then apply it to geodetic */
194+
/* coordinates. */
195+
/* -------------------------------------------------------------------- */
175196
if (srcCRS.getDatum().getTransformType() == Datum.TYPE_GRIDSHIFT) {
176197
srcCRS.getDatum().shift(pt);
177198
}
@@ -202,7 +223,9 @@ private void datumTransform(ProjCoordinate pt) {
202223
tgtGeoConv.convertGeocentricToGeodetic(pt);
203224
}
204225

205-
226+
/* -------------------------------------------------------------------- */
227+
/* Apply grid shift to destination if required. */
228+
/* -------------------------------------------------------------------- */
206229
if (tgtCRS.getDatum().getTransformType() == Datum.TYPE_GRIDSHIFT) {
207230
tgtCRS.getDatum().inverseShift(pt);
208231
}

src/main/java/org/locationtech/proj4j/datum/GeocentricConverter.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,16 @@ public class GeocentricConverter implements java.io.Serializable {
6060
double ep2;
6161

6262
public GeocentricConverter(Ellipsoid ellipsoid) {
63-
this(ellipsoid.getA(), ellipsoid.getB());
63+
// Preserve the ellipsoid value precisions
64+
this(ellipsoid.getA(), ellipsoid.getB(), ellipsoid.getEccentricitySquared());
6465
}
6566

66-
public GeocentricConverter(double a, double b) {
67+
public GeocentricConverter(double a, double b, double e2) {
6768
this.a = a;
6869
this.b = b;
6970
a2 = a * a;
7071
b2 = b * b;
71-
e2 = (a2 - b2) / a2;
72+
this.e2 = e2;
7273
ep2 = (a2 - b2) / b2;
7374
}
7475

@@ -77,6 +78,12 @@ public void overrideWithWGS84Params() {
7778
this.e2 = Ellipsoid.WGS84.getEccentricitySquared();
7879
}
7980

81+
public boolean isEqual(GeocentricConverter gc) {
82+
// Check if geocentricly equal
83+
// https://github.com/OSGeo/PROJ/blob/5.2.0/src/pj_transform.c#L892
84+
return this.a == gc.a && this.e2 == gc.e2;
85+
}
86+
8087
/**
8188
* Converts geodetic coordinates
8289
* (latitude, longitude, and height) to geocentric coordinates (X, Y, Z),

src/main/java/org/locationtech/proj4j/datum/Grid.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ public static void shift(List<Grid> grids, boolean inverse, ProjCoordinate in) {
9191

9292
for (Grid grid : grids) {
9393
ConversionTable table = grid.table;
94+
// don't shift if the grid is invalid
95+
// https://github.com/OSGeo/PROJ/blob/5.2.0/src/pj_gridlist.c#L88
96+
if(table == null) continue;
9497
double epsilon = (Math.abs(table.del.phi) + Math.abs(table.del.lam)) / 10000d;
9598
// Skip tables that don't match our point at all
9699
if (table.ll.phi - epsilon > input.phi
@@ -314,7 +317,6 @@ public static List<Grid> fromNadGrids(String grids) throws IOException {
314317
for (String gridName : grids.split(",")) {
315318
boolean optional = gridName.startsWith("@");
316319
if (optional) gridName = gridName.substring(1);
317-
if (gridName.equals("null")) return null;
318320
try {
319321
mergeGridFile(gridName, gridlist);
320322
} catch (IOException e) {
@@ -331,6 +333,7 @@ private static Grid gridinfoInit(String gridName) throws IOException {
331333
grid.gridName = gridName;
332334
grid.format = "missing";
333335
grid.gridOffset = 0;
336+
if (gridName.equals("null")) return grid;
334337
try(DataInputStream gridDefinition = resolveGridDefinition(gridName)) {
335338
if (gridDefinition == null) {
336339
throw new IOException("Unknown grid: " + gridName);

src/test/java/org/locationtech/proj4j/CoordinateTransformTest.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ public void testFirst() {
4242
*/
4343
}
4444

45-
// @Test
46-
public void FAIL_testEPSG_27700() {
45+
@Test
46+
public void testEPSG_27700() {
4747
checkTransform("EPSG:4326", -2.89, 55.4, "EPSG:27700", 343733.1404, 612144.530677, 0.1);
4848
checkTransformAndInverse(
4949
"EPSG:4326", -2.0301713578021983, 53.35168607080468,
@@ -219,8 +219,14 @@ public void testPROJ4() {
219219
checkTransformToWGS84("EPSG:27700", 612435.55, 1234954.16, 1.9200000236235546, 60.93999999543101, 0.0);
220220
checkTransformToWGS84("EPSG:27700", 327420.988668, 690284.547110, -3.1683134533969364, 56.0998025292667, 0.0);
221221
checkTransformFromWGS84("EPSG:3857", -3.1683134533969364, 56.0998025292667, -352695.04030562507, 7578309.225014557, 0.0);
222-
// TODO https://github.com/locationtech/proj4j/issues/32
223-
//checkTransform("EPSG:27700", 327420.988668, 690284.547110, "EPSG:3857", -352695.04030562507, 7578309.225014557, 0.0);
222+
checkTransform("EPSG:27700", 327420.988668, 690284.547110, "EPSG:3857", -352695.04030562507, 7578309.225014557, 0.0);
223+
checkTransform("EPSG:3857", -352695.04030562507, 7578309.225014557, "EPSG:27700", 327420.988668, 690284.547110, 0.001);
224+
checkTransform("EPSG:31469", 5439627.33, 5661628.09, "EPSG:3857", 1573657.37, 6636624.41, 0.01);
225+
checkTransform("EPSG:3857", 1573657.37, 6636624.41, "EPSG:31469", 5439627.33, 5661628.09, 0.01);
226+
checkTransform("EPSG:2056", 2600670.52, 1199667.32, "EPSG:3857", 829045.23, 5933605.15, 0.01);
227+
checkTransform("EPSG:3857", 829045.23, 5933605.15, "EPSG:2056", 2600670.52, 1199667.32, 0.01);
228+
checkTransform("EPSG:3857", -20037508.342789244, -20037366.780895382, "EPSG:4055", -180.0, -85.01794318500549, 0.001);
229+
checkTransform("EPSG:4055", -180.0, -85.01794318500549, "EPSG:3857", -20037508.342789244, -20037366.780895382, 0.0);
224230
}
225231

226232
@Test

src/test/java/org/locationtech/proj4j/ExampleTest.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,15 +223,12 @@ public void latLonToStereBidirectionalTransform() {
223223
@Test
224224
public void epsgWebMercatorLegacyTest() {
225225
CRSFactory csFactory = new CRSFactory();
226-
String parameters = "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs";
227226
try {
228-
String code = csFactory.readEpsgFromParameters(parameters);
227+
String code = csFactory.readEpsgFromParameters("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs");
229228
Assert.assertEquals(Integer.parseInt(code), 3857);
230229
} catch (IOException e) {
231230
e.printStackTrace();
232231
}
233-
CoordinateReferenceSystem crs = csFactory.createFromParameters("EPSG:3857", parameters);
234-
assertTrue(crs.getDatum().getTransformType() != Datum.TYPE_GRIDSHIFT);
235232
}
236233

237234
private boolean isInTolerance(ProjCoordinate p, double x, double y, double tolerance) {

src/test/java/org/locationtech/proj4j/Proj4VariousTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,8 @@ public void test3ParamToRawSameEllipsoid() {
5959
"+proj=latlong +ellps=bessel", p("0dE 0dN 4.000"), 1e-5);
6060
}
6161

62-
// @Test
63-
public void FAIL_test3ParamToRawSameEllipsoid2() {
64-
// fails - not sure why, possibly missing towgs not handled in same way as PROJ4?
62+
@Test
63+
public void test3ParamToRawSameEllipsoid2() {
6564
checkTransform(
6665
"+proj=latlong +ellps=bessel +towgs84=5,0,0", p("79d00'00.000W 45d00'00.000N 0.0"),
6766
"+proj=latlong +ellps=bessel", p("79dW 45dN 0.000"), 1e-5);

src/test/java/org/locationtech/proj4j/TransformFailures.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
*******************************************************************************/
1616
package org.locationtech.proj4j;
1717

18-
import org.junit.Test;
19-
2018
/**
2119
* A class to run tests which are known to be failures.
2220
* This prevents Maven from running them automatically and reporting failures.
@@ -25,13 +23,4 @@
2523
*/
2624
public class TransformFailures extends BaseCoordinateTransformTest {
2725

28-
@Test
29-
public void testEPSG_27700() {
30-
checkTransform("EPSG:4326", -2.89, 55.4, "EPSG:27700", 343733.1404, 612144.530677, 0.1);
31-
checkTransformAndInverse(
32-
"EPSG:4326", -2.0301713578021983, 53.35168607080468,
33-
"EPSG:27700", 398089, 383867,
34-
0.001, 0.2 * APPROX_METRE_IN_DEGREES);
35-
}
36-
3726
}

0 commit comments

Comments
 (0)