Ferenc Hechler created SIS-432:
----------------------------------
Summary: Using BETA2007.gsb grid throws IllegalArgumentException
Key: SIS-432
URL: https://issues.apache.org/jira/browse/SIS-432
Project: Spatial Information Systems
Issue Type: Bug
Affects Versions: 0.8
Reporter: Ferenc Hechler
Attachments: patch_BETA2007_gsb.png
The following program transforms Gauß-Krüger coordinates (used in Germany) to
the WGS84 format:
{code:title=Main.java}
public static void main(String[] args) throws Exception {
double hochwert = 5500000.0;
double rechtswert = 3500000.0;
CoordinateReferenceSystem sourceCRS = CRS.forCode("EPSG:31467");
CoordinateReferenceSystem targetCRS = CRS.forCode("EPSG:4326");
CoordinateOperation operation = CRS.findOperation(sourceCRS, targetCRS, null);
DirectPosition ptSrc = new DirectPosition2D(hochwert, rechtswert);
DirectPosition ptDst = operation.getMathTransform().transform(ptSrc, null);
System.out.println("Source: " + ptSrc);
System.out.println("Target: " + ptDst);
System.out.println("Expected: POINT(49.63670826166641 8.99895896840875)");
}
{code}
Running the program gives the following output:
{code:title=console.log}
Okt 09, 2018 10:45:00 PM
org.apache.sis.referencing.operation.CoordinateOperationFinder createOperation
WARNUNG: Can not parse “BETA2007.gsb” as a file in the NTv2 format.
Source: POINT(5500000 3500000)
Target: POINT(49.636710642245184 8.99896356404719)
Expected: POINT(49.63670826166641 8.99895896840875)
{code}
As you can see, the result is not as expected.
The reason is, that the grid shift file BETA2007.gsb was not found, as the
warning before already stated: *WARNUNG: Can not parse “BETA2007.gsb” as a file
in the NTv2 format.*
The grid shift file "BETA2007.gsb" can be downloaded from the following
website: http://crs.bkg.bund.de/crseu/crs/descrtrans/BeTA/de_dhdn2etrs_beta.php
There is a link to the ASCII version
[BETA2007.gsa|http://crs.bkg.bund.de/crseu/crs/descrtrans/BeTA/BETA2007.gsa]
and the binary format, which is needed for Apache SIS
[BETA2007.gsb|http://crs.bkg.bund.de/crseu/crs/descrtrans/BeTA/BETA2007.gsb]
I downloaded the BETA2007.gsb file and copied it into the current working
directory (or into the project folder in Eclipse).
Then I started the same main program again and got the follwoing exception:
{code:title=console.log}
Exception in thread "main"
org.apache.sis.referencing.factory.InvalidGeodeticParameterException: Value
‘grid.cellPrecision’ = ? is invalid. Expected a number greater than 0.
at
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory.createParameterizedTransform(DefaultMathTransformFactory.java:1050)
at
org.apache.sis.referencing.factory.sql.EPSGDataAccess.createCoordinateOperation(EPSGDataAccess.java:2927)
at
org.apache.sis.referencing.factory.AuthorityFactoryProxy$34.create(AuthorityFactoryProxy.java:515)
at
org.apache.sis.referencing.factory.AuthorityFactoryProxy$34.create(AuthorityFactoryProxy.java:513)
at
org.apache.sis.referencing.factory.ConcurrentAuthorityFactory.create(ConcurrentAuthorityFactory.java:1679)
at
org.apache.sis.referencing.factory.ConcurrentAuthorityFactory.createCoordinateOperation(ConcurrentAuthorityFactory.java:1590)
at
org.apache.sis.internal.referencing.DeferredCoordinateOperation.create(DeferredCoordinateOperation.java:71)
at
org.apache.sis.referencing.operation.CoordinateOperationRegistry.search(CoordinateOperationRegistry.java:506)
at
org.apache.sis.referencing.operation.CoordinateOperationRegistry.createOperation(CoordinateOperationRegistry.java:333)
at
org.apache.sis.referencing.operation.CoordinateOperationFinder.createOperation(CoordinateOperationFinder.java:236)
at
org.apache.sis.referencing.operation.CoordinateOperationFinder.createOperationStep(CoordinateOperationFinder.java:358)
at
org.apache.sis.referencing.operation.CoordinateOperationFinder.createOperation(CoordinateOperationFinder.java:250)
at
org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory.createOperation(DefaultCoordinateOperationFactory.java:811)
at org.apache.sis.referencing.CRS.findOperation(CRS.java:640)
at de.hechler.apsistest.GK3toWGS84.main(GK3toWGS84.java:23)
Caused by: java.lang.IllegalArgumentException: Value ‘grid.cellPrecision’ = ?
is invalid. Expected a number greater than 0.
at
org.apache.sis.referencing.operation.transform.InterpolatedTransform$Inverse.<init>(InterpolatedTransform.java:440)
at
org.apache.sis.referencing.operation.transform.InterpolatedTransform2D$Inverse.<init>(InterpolatedTransform2D.java:107)
at
org.apache.sis.referencing.operation.transform.InterpolatedTransform2D.createInverse(InterpolatedTransform2D.java:87)
at
org.apache.sis.referencing.operation.transform.InterpolatedTransform.<init>(InterpolatedTransform.java:198)
at
org.apache.sis.referencing.operation.transform.InterpolatedTransform2D.<init>(InterpolatedTransform2D.java:47)
at
org.apache.sis.referencing.operation.transform.InterpolatedTransform.createGeodeticTransformation(InterpolatedTransform.java:235)
at
org.apache.sis.internal.referencing.provider.NTv2.createMathTransform(NTv2.java:128)
at
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory.createParameterizedTransform(DefaultMathTransformFactory.java:1048)
... 14 more
{code}
I debugged into the code and found the following.
In InterpolatedTransform the DataShiftGrid is checked for its accuracy
(getCellPrecision() returns accuracy/10):
{code:title=InterpolatedTransform.java}
tolerance = grid.getCellPrecision();
if (!(tolerance > 0)) { // Use ! for catching NaN.
throw new IllegalArgumentException(Errors.format(
Errors.Keys.ValueNotGreaterThanZero_2, "grid.cellPrecision",
tolerance));
{code}
In NTv2.java a DatumShiftGridFile.Float instance is created to read in the
BETA2007.gsb file. In DatumShiftGridFile.Float the accuracy member variable is
initialized with NaN:
{code:title=DatumShiftGridFile.java}
/**
* The best translation accuracy that we can expect from this file.
*
* <p>This field is initialized to Double#NaN. It is loader responsibility
* to assign a value to this field after DatumShiftGridFile
construction.</p>
*/
protected double accuracy;
{code}
The loader, in this case, is NTv2.java and so it is responsible to set the
accuracy field. And there is code to set the accuracy based on the data in the
BETA2007.gsb file:
{code:title=NTv2.java}
for (int i=0; i<count; i++) {
ensureBufferContains(4 * (Float.SIZE / Byte.SIZE));
ty[i] = (float) (buffer.getFloat() / dy); // Division by dx and dy because
isCellValueRatio = true.
tx[i] = (float) (buffer.getFloat() / dx);
final double accuracy = Math.min(buffer.getFloat() / dy, buffer.getFloat() /
dx);
if (accuracy > 0 && !(accuracy >= grid.accuracy)) { // Use '!' for
replacing the initial NaN.
grid.accuracy = accuracy;
}
}
{code}
So, the grid.accuracy is set to the minimum accuracy from longitude and
latitude.
But as to see in the ASCII file, all precision fields (third and fourth column)
are set to 0.000000:
{code:title=BETA2007.gsa}
...
GS_COUNT 5208
-2.749746 7.165792 0.000000 0.000000
-2.750032 7.067153 0.000000 0.000000
-2.750411 6.968641 0.000000 0.000000
...
-6.330753 2.260298 0.000000 0.000000
-6.338144 2.193162 0.000000 0.000000
-6.345754 2.126569 0.000000 0.000000
END
{code}
(the .gsb file is the binary created from the .gsa file)
And because of this, the grid.accuracy is never set and remains *NaN*.
And then the validation in InterpolatedTransform throws the
IllegalArgumentException.
I patched the BETA2007.gsb file at position 0x168:
!patch_BETA2007_gsb.png!
The change would be in ASCII:
{code:title=BETA2007.gsa(PATCHED)}
...
GS_COUNT 5208
-2.749746 7.165792 0.000001 0.000001
-2.750032 7.067153 0.000000 0.000000
-2.750411 6.968641 0.000000 0.000000
...
-6.330753 2.260298 0.000000 0.000000
-6.338144 2.193162 0.000000 0.000000
-6.345754 2.126569 0.000000 0.000000
END
{code}
So the first shift gets an accuracy value greater then 0.0.
With this patched BETA2007.gsb file the program runs as expected:
{code}
Source: POINT(5500000 3500000)
Target: POINT(49.63670826166641 8.99895896840875)
Expected: POINT(49.63670826166641 8.99895896840875)
{code}
So may be, that this is in real an issue for the BETA2007 file, because it does
not provide an accuracy for any shift value.
But the BETA2007.gsb file from above is the official file and I did not find
any other source providing accuracy values.
On the website it is stated, that the accuracy is less than one meter.
I think the issue could be fixed In NTv2.java, so that it initializes the
grid.accuracy to some default value if it is NaN after checking all shifts.
LocalizationGridBuilder has some similiair intialization:
{code}
(gridPrecision > 0) ? gridPrecision : DEFAULT_PRECISION);
{code}
Maybe this can be done in NTv2 for NaN values.
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)