许多应用系统需要用到地址和经纬度,有时候需要计算相近地址,或者在某地址半径多大之内的其它地址。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