static int hilbert_order(double lng, double lat, int bits) {
static const double LNG_MIN = -180.0, LNG_MAX = 180.0;
static const double LAT_MIN = -90.0, LAT_MAX = 90.0;
int x = (int)((lng - LNG_MIN) / (LNG_MAX - LNG_MIN) * ((1 << bits) - 1));
int y = (int)((lat - LAT_MIN) / (LAT_MAX - LAT_MIN) * ((1 << bits) - 1));
if (x < 0) x = 0; if (x >= (1 << bits)) x = (1 << bits) - 1;
if (y < 0) y = 0; if (y >= (1 << bits)) y = (1 << bits) - 1;
unsigned int d = 0;
for (int s = bits - 1; s >= 0; s--) {
int rx = (x >> s) & 1;
int ry = (y >> s) & 1;
d += (1 << (2 * s)) * ((3 * rx) ^ ry);
if (ry == 0) {
if (rx == 1) { x = (1 << bits) - 1 - x; y = (1 << bits) - 1 - y; }
int tmp = x; x = y; y = tmp;
}
}
return (int)d;
}
x=0 x=1 x=2 x=3 || x=4 x=5 x=6 x=7
+-----+-----+-----+-----++-----+-----+-----+-----+
y=7: | 21 | 22 | 25 | 26 || 37 | 38 | 41 | 42 |
+-----+-----+-----+-----++-----+-----+-----+-----+
y=6: | 20 | 23 | 24 | 27 || 36 | 39 | 40 | 43 |
+-----+-----+-----+-----++-----+-----+-----+-----+
------------------------++-----------------------
y=5: | 19 | 18 | 29 | 28 || 35 | 34 | 45 | 44 |
+-----+-----+-----+-----++-----+-----+-----+-----+
y=4: | 16 | 17 | 30 | 31 || 32 | 33 | 46 | 47 |
+=====+=====+=====+=====++=====+=====+=====+=====+
y=3: | 15 | 12 | 11 | 10 || 53 | 52 | 51 | 48 |
+-----+-----+-----+-----++-----+-----+-----+-----+
y=2: | 14 | 13 | 8 | 9 || 54 | 55 | 50 | 49 |
+-----+-----+-----+-----++-----+-----+-----+-----+
------------------------++-----------------------
y=1: | 1 | 2 | 7 | 6 || 57 | 56 | 61 | 62 |
+-----+-----+-----+-----++-----+-----+-----+-----+
y=0: | 0 | 3 | 4 | 5 || 58 | 59 | 60 | 63 |
+-----+-----+-----+-----++-----+-----+-----+-----+
输入
bit = 3
x = 5
y = 3
//计算过程
第1轮循环 (s = 2)
-
rx = (x >> 2) & 1 = (5>>2=1) & 1 = 1 -
ry = (y >> 2) & 1 = (3>>2=0) & 1 = 0 -
计算
(3 * rx) ^ ry = (3*1) ^ 0 = 3 ^ 0 = 3 -
累加:
d += (1 << (2*2)) * 3 = (1<<4) * 3 = 16 * 3 = 48→ 此时d = 48 -
判断
if (ry == 0):成立-
if (rx == 1):成立 → 执行翻转:-
x = (1<<3)-1 - x = 7 - 5 = 2 -
y = (1<<3)-1 - y = 7 - 3 = 4
-
-
交换
x和y:x = 4, y = 2(原 x=2, y=4 交换后)
-
-
此时
(x, y) = (4, 2)
第2轮循环 (s = 1)
-
当前
x=4(二进制100),y=2(二进制010) -
rx = (4 >> 1) & 1 = (2) & 1 = 0 -
ry = (2 >> 1) & 1 = (1) & 1 = 1 -
计算
(3 * 0) ^ 1 = 0 ^ 1 = 1 -
累加:
d += (1 << (2*1)) * 1 = (1<<2) * 1 = 4 * 1 = 4→ 此时d = 48 + 4 = 52 -
判断
if (ry == 0):ry=1,不成立 → 跳过坐标变换
第3轮循环 (s = 0)
-
当前
x=4(二进制100),y=2(二进制010) -
rx = (4 >> 0) & 1 = 0 -
ry = (2 >> 0) & 1 = 0 -
计算
(3 * 0) ^ 0 = 0 -
累加:
d += (1 << 0) * 0 = 0→d保持52 -
判断
if (ry == 0):成立-
if (rx == 1):rx=0,不翻转 -
交换
x和y:x = 2, y = 4(但后续不再使用)
-
-
循环结束
输出52
Q 第1轮循环 (s = 2) rx = (x >> 2) & 1 = (5>>2=1) & 1 = 1 ry = (y >> 2) & 1 = (3>>2=0) & 1 = 0 计算 (3 * rx) ^ ry = (3*1) ^ 0 = 3 ^ 0 = 3 累加:d += (1 << (2*2)) * 3 = (1<<4) * 3 = 16 * 3 = 48 → 此时 d = 48 这个48是啥意思 在这个图上
可以把 d 看成四 进制数:d = (高位数字)*16 + (低位数字)。
-
高位数字
3决定它在哪个 4×4 大块,乘 16 后就是该大块的起始索引。 -
低位数字(0~15)表示在这个大块内的具体位置。
对于
(5,3),高位=3 → 基地址 48,低位=4 → 最终 52(因为大块内索引 4 对应点(5,3))。
所以 48 就是右下大块的起始索引 ,你可以在矩阵中找到右下大块内最小的数字就是 48(在 y=0, x=7 处)