mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 16:35:40 +02:00
Hilbert and quadkey 128-bit encodings are reversible
This commit is contained in:
+15
-15
@@ -107,22 +107,22 @@ void tiletoepsg3857(long long ix, long long iy, int zoom, double *ox, double *oy
|
|||||||
|
|
||||||
// https://en.wikipedia.org/wiki/Hilbert_curve
|
// https://en.wikipedia.org/wiki/Hilbert_curve
|
||||||
|
|
||||||
void hilbert_rot(unsigned long long n, unsigned long long *x, unsigned long long *y, unsigned long long rx, unsigned long long ry) {
|
static void hilbert_rot(index_t n, unsigned long long *x, unsigned long long *y, index_t rx, index_t ry) {
|
||||||
if (ry == 0) {
|
if (ry == 0) {
|
||||||
if (rx == 1) {
|
if (rx == 1) {
|
||||||
*x = n - 1 - *x;
|
*x = n - 1 - *x;
|
||||||
*y = n - 1 - *y;
|
*y = n - 1 - *y;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned t = *x;
|
unsigned long long t = *x;
|
||||||
*x = *y;
|
*x = *y;
|
||||||
*y = t;
|
*y = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
index_t hilbert_xy2d(unsigned long long n, unsigned long long x, unsigned long long y) {
|
static index_t hilbert_xy2d(index_t n, unsigned long long x, unsigned long long y) {
|
||||||
index_t d = 0;
|
index_t d = 0;
|
||||||
unsigned long long rx, ry;
|
index_t rx, ry;
|
||||||
|
|
||||||
for (index_t s = n / 2; s > 0; s /= 2) {
|
for (index_t s = n / 2; s > 0; s /= 2) {
|
||||||
rx = (x & s) != 0;
|
rx = (x & s) != 0;
|
||||||
@@ -135,8 +135,8 @@ index_t hilbert_xy2d(unsigned long long n, unsigned long long x, unsigned long l
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hilbert_d2xy(index_t n, index_t d, unsigned long long *x, unsigned long long *y) {
|
static void hilbert_d2xy(index_t n, index_t d, unsigned long long *x, unsigned long long *y) {
|
||||||
unsigned long long rx, ry;
|
index_t rx, ry;
|
||||||
index_t t = d;
|
index_t t = d;
|
||||||
|
|
||||||
*x = *y = 0;
|
*x = *y = 0;
|
||||||
@@ -151,21 +151,21 @@ void hilbert_d2xy(index_t n, index_t d, unsigned long long *x, unsigned long lon
|
|||||||
}
|
}
|
||||||
|
|
||||||
index_t encode_hilbert(unsigned long long wx, unsigned long long wy) {
|
index_t encode_hilbert(unsigned long long wx, unsigned long long wy) {
|
||||||
return hilbert_xy2d(1LL << UINT_BITS, wx, wy);
|
return hilbert_xy2d((index_t) 1 << 64, wx, wy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void decode_hilbert(index_t index, unsigned long long *wx, unsigned long long *wy) {
|
void decode_hilbert(index_t index, unsigned long long *wx, unsigned long long *wy) {
|
||||||
hilbert_d2xy(1LL << UINT_BITS, index, wx, wy);
|
hilbert_d2xy((index_t) 1 << 64, index, wx, wy);
|
||||||
}
|
}
|
||||||
|
|
||||||
index_t encode_quadkey(unsigned long long wx, unsigned long long wy) {
|
index_t encode_quadkey(unsigned long long wx, unsigned long long wy) {
|
||||||
index_t out = 0;
|
index_t out = 0;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < UINT_BITS; i++) {
|
for (i = 0; i < 64; i++) {
|
||||||
index_t v = ((wx >> (UINT_BITS - (i + 1))) & 1) << 1;
|
index_t v = ((wx >> (64 - (i + 1))) & 1) << 1;
|
||||||
v |= (wy >> (UINT_BITS - (i + 1))) & 1;
|
v |= (wy >> (64 - (i + 1))) & 1;
|
||||||
v = v << (64 - 2 * (i + 1));
|
v = v << (128 - 2 * (i + 1));
|
||||||
|
|
||||||
out |= v;
|
out |= v;
|
||||||
}
|
}
|
||||||
@@ -196,9 +196,9 @@ void decode_quadkey(index_t index, unsigned long long *wx, unsigned long long *w
|
|||||||
|
|
||||||
*wx = *wy = 0;
|
*wx = *wy = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < 8; i++) {
|
for (size_t i = 0; i < 16; i++) {
|
||||||
*wx |= ((unsigned long long) decodex[(index >> (8 * i)) & 0xFF]) << (4 * i);
|
*wx |= ((index_t) decodex[(index >> (8 * i)) & 0xFF]) << (4 * i);
|
||||||
*wy |= ((unsigned long long) decodey[(index >> (8 * i)) & 0xFF]) << (4 * i);
|
*wy |= ((index_t) decodey[(index >> (8 * i)) & 0xFF]) << (4 * i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -124,20 +124,29 @@ TEST_CASE("Projection", "projection") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Quadkey index", "quadkey index") {
|
TEST_CASE("Quadkey index", "quadkey index") {
|
||||||
unsigned x = (unsigned) 1234567890;
|
unsigned long long a = (unsigned) 1234567890;
|
||||||
unsigned y = (unsigned) 3210987654;
|
unsigned long long b = (unsigned) 3210987654;
|
||||||
|
|
||||||
|
unsigned long long x = (b << 32) | a;
|
||||||
|
unsigned long long y = (a << 32) | b;
|
||||||
index_t encoded;
|
index_t encoded;
|
||||||
unsigned long long nx, ny;
|
unsigned long long nx, ny;
|
||||||
|
|
||||||
encoded = encode_quadkey(x, y);
|
encoded = encode_quadkey(x, y);
|
||||||
REQUIRE((unsigned long long) encoded == 7338499239188161052);
|
// the *bottom* 64 bits of the 128-bit encoding
|
||||||
|
// are the same as the 64-bit encoding of a, b
|
||||||
|
REQUIRE((unsigned long long) encoded == 7338499239188161052ULL);
|
||||||
|
REQUIRE((unsigned long long) (encoded >> 64) == 11163131681630900524ULL);
|
||||||
decode_quadkey(encoded, &nx, &ny);
|
decode_quadkey(encoded, &nx, &ny);
|
||||||
REQUIRE(nx == x);
|
REQUIRE(nx == x);
|
||||||
REQUIRE(ny == y);
|
REQUIRE(ny == y);
|
||||||
|
|
||||||
encoded = encode_hilbert(x, y);
|
encoded = encode_hilbert(y, x);
|
||||||
REQUIRE((unsigned long long) encoded == 8447864191955811122);
|
// the *top* 64 bits of the 128-bit encoding
|
||||||
decode_hilbert(encoded, &nx, &ny);
|
// of the 64-bit encoding of a, b
|
||||||
|
REQUIRE((unsigned long long) (encoded >> 64) == 8447864191955811122ULL);
|
||||||
|
REQUIRE((unsigned long long) encoded == 16122461378071376152ULL);
|
||||||
|
decode_hilbert(encoded, &ny, &nx);
|
||||||
REQUIRE(nx == x);
|
REQUIRE(nx == x);
|
||||||
REQUIRE(ny == y);
|
REQUIRE(ny == y);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user