[ 
https://issues.apache.org/jira/browse/SIS-432?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Martin Desruisseaux reassigned SIS-432:
---------------------------------------

    Assignee: Martin Desruisseaux

> 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)

Reply via email to