Sam Wilson's Journal

NewsArchives

 «   »

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)
	{
		trigger_error('Bad Format min: 2', E_USER_ERROR);
	}
	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;
}

[Keywords: , , , , , , , ] [No comments] [Permanent link]

Comments:

  1. Leave a comment:

    You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

« »