GeoHash.net是一个轻巧的高性能C#库,用于编码和解码字符串和整数地理句。
托多
这是如何使用geohash.net库的快速示例:
using NetGeohash ;
// Encode latitude and longitude coordinates into a geohash string
string geohash = Geohash . Encode ( 37.421999 , - 122.084057 , 9 ) ;
// Decode the geohash string into latitude and longitude coordinates
( double latitude , double longitude ) = Geohash . Decode ( geohash ) ;
// Encode the geohash string into an integer format
ulong geohashInt = Geohash . EncodeToInt64 ( 37.421999 , - 122.084057 , 9 ) ;
// Decode the integer geohash into latitude and longitude coordinates
( latitude , longitude ) = Geohash . DecodeFromInt64 ( geohashInt ) ; GeoHash是一个地理编码系统,可让您使用短的字母字符串或整数来表示地理位置。它是由Gustavo Niemeyer于2008年开发的,此后已成为编码和索引空间数据的流行方法。
地理施工背后的概念是采用纬度和经度坐标,并将其转换为更紧凑的形式。这是通过将地球表面递归分为矩形细胞而实现的,然后将其分配给唯一的标识符。地球上的长度决定了精度的水平,较长的地理位化代表较小的区域。
GeoHash细胞具有一些值得注意的特性:
例如,要为纬度37.7749和经度的位置生成一个地理字符串,精确水平为12,我们可以遵循这三个阶段:
通过映射到单位间隔[0,1],将纬度和经度量化为32位整数,并乘以2^32( exp2(32) ):
纬度采用[-90,90]的范围,因此,纬度的32位整数表示为
lat32 = floor ( exp2 ( 32 ) * ( latitude + 90 ) / 180 )在我们的情况下,它等于3048827870( 0b10110101101110010110101111011110 )
同样对于经度[-180,180]:
lng32 = floor ( exp2 ( 32 ) * ( longitude + 180 ) / 360 )在我们的情况下,它等于686963316( 0b101000111100100011101001110100 )
32位量化的纬度和经度被咬合,以产生64位值(整数地理)。
下图说明了操作。

注意:纬度和经度分别占据均匀和奇数。
在我们的运行示例中,整数GeoHash是:5589511709871930228( 0b0100110110010001111011110100100100011110110011010111101101110100 )
该数字应以较低的精度进行。整数GeoHash的精度由N高点组成,因此我们需要截断多余的位。我们可以通过位移动操作来做到这一点:
hash = interleaved >> ( sizeof ( ulong ) * BITS_PER_BYTE - log2 ( 32 ) * precision ) // 64 - 5 * precision对于我们的示例,为349344481866995639( 0b010011011001000111101111010010010001111011001101011110110111 )。
注意:此步骤最终提供了GeoHash的关键前缀属性:以较低精度为点的Geohash是Geohash的前缀,以较高的精度为前缀。因此,接近搜索可以简化为匹配的GeoHash前缀(作为第一次通过)。
字符串GeoHash是通过Base32编码从整数GeoHash获得的。这是标准的,除了选择字母。每个GeoHash字符代表一个5位( log2(32) )二进制值,整个GeoHash字符串由多个串联的5位值组成。
0123456789bcdefghjkmnpqrstuvwxyz
编码始于高点,为每个精度的每个字符都消耗5位整数地理什。结果,最大精度是12个字符或60位。
将二进制值分为5位的组,然后将每个组转换为相应的基本-32字符:
01001 ( 9) - 9
10110 (22) - q
01000 ( 8) - 8
11110 (30) - y
11110 (30) - y
10010 (18) - k
01000 ( 8) - 8
11110 (30) - y
11001 (25) - t
10101 (21) - p
11101 (29) - x
10111 (23) - r
加入所有基本32个字符,形成最终的GeoHash字符串: 9q8yyk8ytpxr
对于内部用例,整数GeoHash通常就足够了。 Base32步骤在此处包括在内。
BenchmarkDotNet =v0.13.5, OS =Windows 11 (10.0.22000.1696/21H2/SunValley)
AMD Ryzen 9 3900X, 1 CPU, 24 logical and 12 physical cores
.NET SDK =8.0.100-preview.1.23115.2
[Host] : .NET 8.0.0 (8.0.23.11008), X64 RyuJIT AVX2
Job-KKMPKU : .NET 8.0.0 (8.0.23.11008), X64 RyuJIT AVX2
Jit =RyuJit Platform =X64 Runtime =.NET 8.0
| 方法 | 输入 | 意思是 | 错误 | stddev | 代码大小 | Gen0 | 分配 |
|---|---|---|---|---|---|---|---|
| Netgeohash | k | 8.112 ns | 0.1881 ns | 0.2090 ns | 1,717 b | - | - |
| NetCoreGeoHash | k | 145.271 ns | 0.8736 ns | 0.7295 ns | 18 b | 0.0038 | 32 b |
| ngeohashlib | k | 143.414 ns | 0.8529 ns | 0.7561 ns | 9 b | 0.0229 | 192 b |
| Netgeohash | yd | 8.442 ns | 0.1032 ns | 0.0965 ns | 1,717 b | - | - |
| NetCoreGeoHash | yd | 166.305 ns | 0.8682 ns | 0.8121 ns | 18 b | 0.0038 | 32 b |
| ngeohashlib | yd | 169.663 ns | 1.0957 ns | 1.0249 ns | 9 b | 0.0229 | 192 b |
| Netgeohash | 6n3 | 9.442 ns | 0.1746 ns | 0.1633 ns | 1,717 b | - | - |
| NetCoreGeoHash | 6n3 | 192.502 ns | 2.0566 ns | 1.9238 ns | 18 b | 0.0038 | 32 b |
| ngeohashlib | 6n3 | 202.150 ns | 1.9676 ns | 1.8405 ns | 9 b | 0.0229 | 192 b |
| Netgeohash | zvgk | 10.183 ns | 0.1023 ns | 0.0907 ns | 1,717 b | - | - |
| NetCoreGeoHash | zvgk | 218.244 ns | 1.4455 ns | 1.3521 ns | 18 b | 0.0038 | 32 b |
| ngeohashlib | zvgk | 223.580 ns | 0.7643 ns | 0.6776 ns | 9 b | 0.0229 | 192 b |
| Netgeohash | T05KH | 10.726 ns | 0.2016 ns | 0.1886 ns | 1,717 b | - | - |
| NetCoreGeoHash | T05KH | 310.208 ns | 0.9773 ns | 0.8663 ns | 18 b | 0.0038 | 32 b |
| ngeohashlib | T05KH | 263.364 ns | 2.2418 ns | 2.0970 ns | 9 b | 0.0229 | 192 b |
| Netgeohash | B5CV2H | 11.413 ns | 0.0796 ns | 0.0706 ns | 1,717 b | - | - |
| NetCoreGeoHash | B5CV2H | 328.490 ns | 2.4518 ns | 2.1735 ns | 18 b | 0.0038 | 32 b |
| ngeohashlib | B5CV2H | 283.862 ns | 2.9657 ns | 2.7741 ns | 9 b | 0.0229 | 192 b |
| Netgeohash | VVEYJ80 | 12.114 ns | 0.1749 ns | 0.1636 ns | 1,717 b | - | - |
| NetCoreGeoHash | VVEYJ80 | 358.143 ns | 0.9470 ns | 0.7908 ns | 18 b | 0.0038 | 32 b |
| ngeohashlib | VVEYJ80 | 318.725 ns | 1.7533 ns | 1.6400 ns | 9 b | 0.0229 | 192 b |
| Netgeohash | F7Y53XJT | 12.676 ns | 0.2287 ns | 0.2140 ns | 1,717 b | - | - |
| NetCoreGeoHash | F7Y53XJT | 380.157 ns | 2.2520 ns | 2.1065 ns | 18 b | 0.0038 | 32 b |
| ngeohashlib | F7Y53XJT | 334.277 ns | 1.0733 ns | 1.0039 ns | 9 b | 0.0229 | 192 b |
| Netgeohash | TRM92JKBV | 12.990 ns | 0.1217 ns | 0.1139 ns | 1,717 b | - | - |
| NetCoreGeoHash | TRM92JKBV | 404.136 ns | 1.9322 ns | 1.7128 ns | 18 b | 0.0038 | 32 b |
| ngeohashlib | TRM92JKBV | 374.209 ns | 1.0807 ns | 1.0109 ns | 9 b | 0.0229 | 192 b |
| Netgeohash | DRMQ3GX6ZT | 13.861 ns | 0.1824 ns | 0.1706 ns | 1,717 b | - | - |
| NetCoreGeoHash | DRMQ3GX6ZT | 429.735 ns | 1.6946 ns | 1.4151 ns | 18 b | 0.0038 | 32 b |
| ngeohashlib | DRMQ3GX6ZT | 400.585 ns | 1.9080 ns | 1.7847 ns | 9 b | 0.0229 | 192 b |
| Netgeohash | 9zefgnuj7dw | 14.265 ns | 0.2997 ns | 0.2803 ns | 1,717 b | - | - |
| NetCoreGeoHash | 9zefgnuj7dw | 455.781 ns | 3.3098 ns | 2.9341 ns | 18 b | 0.0038 | 32 b |
| ngeohashlib | 9zefgnuj7dw | 416.747 ns | 2.7821 ns | 2.6023 ns | 9 b | 0.0229 | 192 b |
| Netgeohash | K9M2H7T1N0C2 | 14.864 ns | 0.3210 ns | 0.3153 ns | 1,717 b | - | - |
| NetCoreGeoHash | K9M2H7T1N0C2 | 479.624 ns | 1.5628 ns | 1.3854 ns | 18 b | 0.0038 | 32 b |
| ngeohashlib | K9M2H7T1N0C2 | 467.252 ns | 1.3795 ns | 1.2904 ns | 9 b | 0.0229 | 192 b |

| 方法 | 纬度 | 经度 | 精确 | 意思是 | 错误 | stddev | 代码大小 | Gen0 | 分配 |
|---|---|---|---|---|---|---|---|---|---|
| Netgeohash | -89.127865 | -179.438962 | 7 | 20.69 ns | 0.146 ns | 0.129 ns | 906 b | 0.0048 | 40 b |
| NetCoreGeoHash | -89.127865 | -179.438962 | 7 | 195.04 ns | 0.632 ns | 0.528 ns | 14 b | 0.0172 | 144 b |
| ngeohashlib | -89.127865 | -179.438962 | 7 | 324.45 ns | 3.044 ns | 2.848 ns | 19 b | 0.0458 | 384 b |
| Netgeohash | -41.2858 | 174.7868 | 12 | 24.77 ns | 0.352 ns | 0.329 ns | 906 b | 0.0057 | 48 b |
| NetCoreGeoHash | -41.2858 | 174.7868 | 12 | 318.08 ns | 2.079 ns | 1.944 ns | 14 b | 0.0181 | 152 b |
| ngeohashlib | -41.2858 | 174.7868 | 12 | 493.78 ns | 2.879 ns | 2.552 ns | 19 b | 0.0687 | 576 b |
| Netgeohash | -12.347856 | 34.890273 | 3 | 17.95 ns | 0.215 ns | 0.201 ns | 906 b | 0.0038 | 32 b |
| NetCoreGeoHash | -12.347856 | 34.890273 | 3 | 104.91 ns | 0.616 ns | 0.546 ns | 14 b | 0.0162 | 136 b |
| ngeohashlib | -12.347856 | 34.890273 | 3 | 167.74 ns | 2.523 ns | 2.360 ns | 19 b | 0.0277 | 232 b |
| Netgeohash | 45.678912 | 92.45236 | 4 | 18.39 ns | 0.313 ns | 0.293 ns | 906 b | 0.0038 | 32 b |
| NetCoreGeoHash | 45.678912 | 92.45236 | 4 | 127.05 ns | 1.053 ns | 0.985 ns | 14 b | 0.0162 | 136 b |
| ngeohashlib | 45.678912 | 92.45236 | 4 | 209.17 ns | 1.549 ns | 1.449 ns | 19 b | 0.0305 | 256 b |
| Netgeohash | 52.5174 | 13.409 | 12 | 24.64 ns | 0.299 ns | 0.280 ns | 906 b | 0.0057 | 48 b |
| NetCoreGeoHash | 52.5174 | 13.409 | 12 | 310.05 ns | 1.637 ns | 1.451 ns | 14 b | 0.0181 | 152 b |
| ngeohashlib | 52.5174 | 13.409 | 12 | 498.72 ns | 5.374 ns | 5.027 ns | 19 b | 0.0687 | 576 b |
| Netgeohash | 80.294617 | 19.543821 | 5 | 18.82 ns | 0.228 ns | 0.191 ns | 906 b | 0.0038 | 32 b |
| NetCoreGeoHash | 80.294617 | 19.543821 | 5 | 152.24 ns | 0.561 ns | 0.498 ns | 14 b | 0.0162 | 136 b |
| ngeohashlib | 80.294617 | 19.543821 | 5 | 242.98 ns | 2.265 ns | 2.008 ns | 19 b | 0.0391 | 328 b |

我鼓励Geohash.net贡献!如果您遇到错误或对新功能有建议,请随时在Github上打开问题或提交拉动请求。我一直在寻找增强图书馆并为社区提供更多价值的方法。
GeoHash.net基于Michael McLoughlin的研究和发现。他在GO中的Geohash算法上的地理塑料工作以及实施高性能地塑料算法的实施,可以在Golang大会的Geohash中找到。