[ https://issues.apache.org/jira/browse/SIS-432?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16644651#comment-16644651 ]
Martin Desruisseaux commented on SIS-432: ----------------------------------------- Thank you very much for this impressive analysis! Yes I agree, we should define some fallback for the case where the file does not define a precision. I will try to do that no later than Saturday. > 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 > Assignee: Martin Desruisseaux > Priority: Major > 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)