# Extracting coordinates from single 60 bit hex numbers

Thanks to the wonderful people on Stackoverflow, I’m making some progress with figuring out how some geographic information is saved in a DB2 database that I’m working with.

it turns out that, rather than using the spatial functionality of DB2 (which would make sense, but considering the source of this database, I wouldn’t ask for too much), coordinate pairs are being stored as Morton codes in a 16-byte Character column.

So far, I’ve sorted out decoding the coordinate values, and can shuffle points predictably on my test map; now I’m just trying to figure out what grid that these coordinates are on. I’m fairly certain (not that I know anything about these things) that it’s somehow related to the MGA grid, because 0 east is at almost exactly 114°, which is where MGA zone 50 starts (the ‘almost’ comes from my point-and-click measurement technique).

But I don’t know where I’m going next; I’ll leave it till the morning.

My test code for this has been in PHP, and I needed something to convert big numbers between bases; hadn’t realised that the BC math library didn’t include `base_convert()`, so I found the one below.

```/**
* Convert an arbitrary-length number between arbitrary bases.
* Copied, and very slightly translated, from
* http://www.technischedaten.de/pmwiki2/pmwiki.php?n=Php.BaseConvert
*
* @param \$value
* @param \$from_base
* @param \$to_base
* @return string
*/
function bc_base_convert(\$value, \$from_base, \$to_base)
{
\$valid_digits = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
if (min(\$from_base, \$to_base) < 2)
{
}
if (max(\$from_base, \$to_base) > strlen(\$valid_digits))
{
trigger_error('Bad Format max: ' . strlen(\$valid_digits), E_USER_ERROR);
}
\$dezi = '0';
\$level = 0;
\$result = '';
\$value = trim(strval(\$value), "\r\n\t +");
\$sign = ('-' === \$value{0}) ? '-' : '';
\$value = ltrim(\$value, "-0");
\$len = strlen(\$value);
for (\$i = 0; \$i < \$len; \$i++)
{
\$wert = strpos(\$valid_digits, \$value{\$len - 1 - \$i});
if (FALSE === \$wert)
{
trigger_error('Bad Char in input 1', E_USER_ERROR);
}
if (\$wert >= \$from_base)
{
trigger_error('Bad character in input 2', E_USER_ERROR);
}
\$dezi = bcadd(\$dezi, bcmul(bcpow(\$from_base, \$i), \$wert));
}
if (\$to_base == 10)
{
return \$sign . \$dezi; // Shortcut for base 10
}
while (1 !== bccomp(bcpow(\$to_base, \$level++), \$dezi));
for (\$i = \$level - 2; \$i >= 0; \$i--)
{
\$factor = bcpow(\$to_base, \$i);
\$zahl = bcdiv(\$dezi, \$factor, 0);
\$dezi = bcmod(\$dezi, \$factor);
\$result .= \$valid_digits{\$zahl};
}
\$result = empty(\$result) ? '0' : \$result;
return \$sign . \$result;
}
```