I decided to try for a Hilbert ordering by (1) computing a square bounding box of all points, (2) converting each point to a fraction (0..1, 0..1) within that bounding box, (3) multiplying the fractional coordinates by a large integer, (4) convert the coordinates to a pair of integers, (5) computing a Hilbert value and (6) sorting by it. Actually computing the Hilbert number proved very tricky to get right. Here's my method for doing so (C#).
ulong ToHilbertOrder(uint x, uint y)
{
ulong result = 0;
for (int i = 31; i >= 0; i--)
{
uint mask = (1u << i) - 1;
uint xb = x >> i;
uint yb = y >> i;
uint distance = (xb << 1) ^ (xb ^ yb);
x &= mask;
y &= mask;
result = (result << 2) + distance;
if (yb == 0) {
// Transpose \
G.Swap(ref x, ref y);
if (xb != 0) {
// Transpose /
x = mask - x;
y = mask - y;
}
}
}
return result;
}
Despite the embarrassing amount of time it took to write that code, I'm still not really happy with the Hilbert order, because if the points are not uniformly distributed (or fairly one-dimensional), there are often several long-distance jumps in the resulting order.
Oh well, I suppose it's good enough for now. I can't really afford to spend any more time on it.
If I'm not mistaken, the simpler Z-order is achieved simply by interleaving bits, which is a much simpler task. I decided it was not a very good ordering because adjacent Z-order numbers are sometimes separated by large distances (I didn't actually experiment with it though).