许多应用系统需要用到地址和经纬度,有时候需要计算相近地址,或者在某地址半径多大之内的其它地址。Gis计算可以借助Postgresql或者Redis,也可以调用百度地图和高德地图等接口。但这些都引入了外部依赖。这里的GeoHash以Base32编码来表示一个经纬度,两个坐标的GeoHash前缀字符串相同越多,说明它们的距离越近。

Nuget包:NewLife.Core

源码:https://github.com/NewLifeX/X/blob/master/NewLife.Core/Data/GeoHash.cs

视频:https://www.bilibili.com/video/BV1Je4y1E7rg


基本原理

一维编码表示一个矩形区域,前缀表示更大区域,例如北京wx4fbzdvs80包含在wx4fbzdvs里面。这个特性可以用于附近地点搜索。

GeoHash编码位数及距离关系:

  • 1位,+-2500km;
  • 2位,+-630km;
  • 3位,+-78km;
  • 4位,+-20km;
  • 5位,+-2.4km;
  • 6位,+-610m;
  • 7位,+-76m;
  • 8位,+-19m;
  • 9位,+-2m;


编码与解码

主要编码与解码

/// <summary>编码坐标点为GeoHash字符串</summary>
/// <param name="longitude">经度</param>
/// <param name="latitude">纬度</param>
/// <param name="charCount">字符个数。默认9位字符编码,精度2米</param>
/// <returns></returns>
public static String Encode(Double longitude, Double latitude, Int32 charCount = 9);

/// <summary>解码GeoHash字符串为坐标点</summary>
/// <param name="geohash"></param>
/// <returns></returns>
public static GeoPoint Decode(String geohash);

Encode 用于把一个经纬度左边编码成为base32字符串;

Decode 用于把一个geohash字符串解码得到经纬度坐标;


在使用时,对比一下两个geohash开头相同的字符格式,即可得到比较粗的距离。


总结

Redis有GEO功能,可以精确计算指定半径之内的节点 分布式缓存NewLife.Redis


根据地址获取经纬度,可以使用百度地图接口或高德地图接口 百度地图接口BaiduMap 高德地图接口AMap