I assumed that would imply "f" format specifier, but probably I was mistaken, and it should be "d"
Unfortunately, it doesn't seem to be as simple as that. Either that or I am totally misunderstanding the results I am getting
Using this code:
use DBD::SQLite;
use Data::Dumper;
use strict;
use warnings;
my $dbh = DBI->connect("dbi:SQLite:uri=file:osopenusrn_202203.gpkg?mod
+e=rwc");
my $tab = $dbh->prepare("SELECT * FROM openUSRN");
$tab->execute;
my $data = $tab->fetchrow_hashref;
my @test = unpack "(H2)2 CCVd6CVV", $data->{'geometry'};
foreach my $t(@test) {
print "$t\n";
}
print "\n-----\n\n";
printf ('%f ', $test[4]);
printf ('%f', $test[6]);
I get this output
47 | - G
50 | - P
0 - version
5 - flags (Little Endian & envelope type 2)
27700 - SRS (OSGB 1936)
637590.385 | - min_x -|
642426.601 | - max_x |
309577.58 | - min_y |- envelope
310361.391000001 | - max_y |
0 | - min_z |
0 | - max_z -|
1 - StandardGeoPackageBinary encoding (Little En
+dian)
1005 - StandardGeoPackageBinary type (MultiLineStr
+ing Z)
34 - Number of LineStrings
-----
27700.000000 642426.601000
The StandardGeoPackageBinary Spec (section 8.2.2) tell us that there are only three data types.
A single byte plus the following:
An Unsigned Integer is a 32-bit (4-byte) data type that encodes a nonnegative integer in the range
(0, 4,294,967,295).
A Double is a 64-bit (8-byte) double precision datatype that encodes a double precision number using the IEEE
754
double precision format.
Applying a simple sanity check to the results I get, show that byte 'C' makes sense - e.g. 'GP' and the 'flags'. Also the unsigned int 'V' makes sense. 1005 is a perfectly sensible result for the StandardGeoPackageBinary type.
The problem comes with the IEEE 754 double. Data::IEEE754 says that: If you can require Perl 5.10 or greater then this module is pointless. Just use the d> and f> pack formats instead!. I am using Perl 5.32.1 so 'd' should give me an IEEE 754 double. It pulls the right number of bytes off the binary (otherwise the following values would be gobbledegook) but it returns values that don't make sense.
The OBGB SRS doesn't use latitude and longitude. Instead, it uses easting and northing (x, y) coordinates. They have to be integers in the range 0-670000 for x and 0-140000 for y.
I'm beginning to think that I must be interpreting the data wrongly.
Is there any other way that a Little Endian IEEE 754 double can be decoded? Is it somehow platform dependent? Although surely the purpose of IEEE 754 is to make data universal and remove the platform dependency (once the endiness is established). |