geohash-net实现

基于c#语言 geohash算法基本实现源码,参见: https://github.com/sharonjl/geohash-net , 源码中具体包含如下方法:

  • String CalculateAdjacent(String hash, Direction direction);               //根据指定hash码,获取相邻的上下左右矩形框hash码
  • double[] Decode(String geohash);                                                  //根据指定hash码返回经纬度
  • String Encode(double latitude, double longitude, int precision = 12); //根据经纬度和指定的hash码长度获取hash码

但在实际应用的过程中,由于GeoHash是将区域划分为一个个规则矩形,并对每个矩形进行编码,这样在查询附近POI信息时会导致以下问题,比如红色的点是我们的位 置,绿色的两个点分别是附近的两个餐馆,但是在查询的时候会发现距离较远餐馆的GeoHash编码与我们一样(因为在同一个GeoHash区域块上),而 较近餐馆的GeoHash编码与我们不一致。这个问题往往产生在边界处,如下图:

解决方案:在查询时,除了使用定位点的GeoHash编码进行匹配外,还使用周围8个区域的GeoHash编码,取出相邻的8个区域范围内的所有餐馆作为第一层过滤,然后根据当前位置计算出与8个相邻区域内每个餐厅的距离,按距离的由小到大顺序返回结果,扩展代码如下:

  • 获取指定hash对应矩形框相邻的8个区域示例代码:

    /// <summary>
            /// 获取九个格子 顺序 本身 上、下、左、右、 左上、 右上、 左下、右下
            /// </summary>
            /// <param name="geohash"></param>
            /// <returns></returns>
            public List<string> GetGeoHashExpand(String geohash)
            {
                String geohashTop = CalculateAdjacent(geohash, Direction.Top);//上
    
                String geohashBottom = CalculateAdjacent(geohash, Direction.Bottom);//下
    
                String geohashLeft = CalculateAdjacent(geohash, Direction.Left);//左
    
                String geohashRight = CalculateAdjacent(geohash, Direction.Right);//右
    
                String geohashTopLeft = CalculateAdjacent(geohashLeft, Direction.Top);//左上
    
                String geohashTopRight = CalculateAdjacent(geohashRight, Direction.Top);//右上
    
                String geohashBottomLeft = CalculateAdjacent(geohashLeft, Direction.Bottom);//左下
    
                String geohashBottomRight = CalculateAdjacent(geohashRight, Direction.Bottom);//右下
    
                return new List<string>() { geohash, geohashTop, geohashBottom, geohashLeft, geohashRight,                                     geohashTopLeft, geohashTopRight, geohashBottomLeft, geohashBottomRight };
    
            }
  • 计算两点之间距离示例代码

    //地球半径,单位米
            private const double EARTH_RADIUS = 6378137;
            /// <summary>
            /// 计算两点位置的距离,返回两点的距离,单位 米
            /// 该公式为GOOGLE提供,误差小于0.2米
            /// </summary>
            /// <param name="lat1">第一点纬度</param>
            /// <param name="lng1">第一点经度</param>
            /// <param name="lat2">第二点纬度</param>
            /// <param name="lng2">第二点经度</param>
            /// <returns></returns>
            public static double GetDistance(double lat1, double lng1, double lat2, double lng2)
            {
                double radLat1 = Rad(lat1);
                double radLng1 = Rad(lng1);
                double radLat2 = Rad(lat2);
                double radLng2 = Rad(lng2);
                double a = radLat1 - radLat2;
                double b = radLng1 - radLng2;
                double result = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2))) * EARTH_RADIUS;
                return result;
            }
    
            /// <summary>
            /// 经纬度转化成弧度
            /// </summary>
            /// <param name="d"></param>
            /// <returns></returns>
            private static double Rad(double d)
            {
                return (double)d * Math.PI / 180d;
            }
  • 计算hash码对应矩形框经纬度范围代码(左下角、右上角),参考: https://github.com/aerisweather/node-geohash/blob/master/main.js , c#实现示例码如下:

     public double[] Decode_bbox(string hash_string)
            {
                bool isLon = true;
                double maxLat = 90,minLat = -90,maxLon = 180,minLon = -180,mid;
    
                int hashValue = 0;
                int l = hash_string.Length;
                for (int i = 0; i < l; i++)
                {
                    string code = Convert.ToString(hash_string[i]);
                    hashValue = BASE32_CODES_DICT[code];
    
                    for (var bits = 4; bits >= 0; bits--)
                    {
                        var bit = (hashValue >> bits) & 1;
                        if (isLon)
                        {
                            mid = (maxLon + minLon) / 2;
                            if (bit == 1)
                            {
                                minLon = mid;
                            }
                            else
                            {
                                maxLon = mid;
                            }
                        }
                        else
                        {
                            mid = (maxLat + minLat) / 2;
                            if (bit == 1)
                            {
                                minLat = mid;
                            }
                            else
                            {
                                maxLat = mid;
                            }
                        }
                        isLon = !isLon;
                    }
                }
                return new double[] { minLat, minLon, maxLat, maxLon };
            }
  • 基于以上的代码,在实际应用中基本可完成对附件范围内事物的搜索以及在地图中进行区域标识
时间: 2024-10-22 13:58:01

geohash-net实现的相关文章

故障定位之查找附近点GeoHash研讨

随着移动终端的普及,很多应用都基于LBS功能,附近的某某(餐馆.银行.妹纸等等). 基础数据中,一般保存了目标位置的经纬度:利用用户提供的经纬度,进行对比,从而获得是否在附近. 目标:查找附近的XXX,由近到远返回结果,且结果中有与目标点的距离. 针对查找附近的XXX,提出两个方案,如下: 一.方案A:=================================================================================================

php通过geohash算法实现查找附近的商铺

geohash有以下几个特点: 首先,geohash用一个字符串表示经度和纬度两个坐标.利用geohash,只需在一列上应用索引即可. 其次,geohash表示的并不是一个点,而是一个矩形区域.比如编码wx4g0ec19,它表示的是一个矩形区域. 使用者可以发布地址编码,既能表明自己位于北海公园附近,又不至于暴露自己的精确坐标,有助于隐私保护. 第三,编码的前缀可以表示更大的区域.例如wx4g0ec1,它的前缀wx4g0e表示包含编码wx4g0ec1在内的更大范围. 这个特性可以用于附近地点搜索

LBS地理位置距离计算方法之geohash算法

随着移动终端的普及,很多应用都基于LBS功能,附近的某某(餐馆.银行.妹纸等等).基础数据中,一般保存了目标位置的经纬度:利用用户提供的经纬度,进行对比,从而获得是否在附近.这里需要在设置出一个字段,是关于编码的字段,一会看下文哈…… 地理位置距离实现目标:查找附近多少公里内的人或者商家 比如:微信.陌陌.美团.基于O2O的一些APP这些应用或者移动网页都需要用到地理位置计算 目前来说:移动地理位置距离计算比较好的算法是geohash,特此整理分享. geohash有以下几个特点: 第一:geo

GeoHash解析及java实现

GeoHash解析请参考这里: http://www.open-open.com/lib/view/open1417940079964.html java实现GeoHash,代码已注释. import java.util.BitSet; import java.util.HashMap; /** * 地理知识补充: Latitude(纬度)[-90, 90],Longitude(经度)[-180, 180] * * @author FengKang 2014-10-03 * */ public

geohash基本原理

geohash基本原理是将地球理解为一个二维平面,将平面递归分解成更小的子块,每个子块在一定经纬度范围内拥有相同的编码,这种方式简单粗暴,可以满足对小规模的数据进行经纬度的检索 目录: 经纬度常识 认识geohash geohash算法 geohash原理 对照表 经纬度常识 经线是纵的,经度是横的,用于表示不同的经线,纬线是横的,纬度是纵的,用于表示不同的纬线,如下图    纬线:地球仪上的横线,lat,赤道是最大的纬线,从赤道开始分为北纬和南纬,都是0-90°,纬线是角度数值,并不是米: 经

查找附近点--Geohash方案讨论

转载自:http://blog.csdn.net/wangliqiang1014/article/details/9143825 随着移动终端的普及,很多应用都基于LBS功能,附近的某某(餐馆.银行.妹纸等等). 基础数据中,一般保存了目标位置的经纬度:利用用户提供的经纬度,进行对比,从而获得是否在附近. 目标:查找附近的XXX,由近到远返回结果,且结果中有与目标点的距离. 针对查找附近的XXX,提出两个方案,如下: 一.方案A:=================================

GeoHash核心原理解析 - OPEN 开发经验库

阅读目录 引子 一.感性认识GeoHash 二.GeoHash算法的步骤 三.GeoHash Base32编码长度与精度 三.GeoHash算法 四.使用注意点 引子 机机是个好动又好学的孩子,平日里就喜欢拿着手机地图点点按按来查询一些好玩的东西.某一天机机到北海公园游玩,肚肚饿了,于是乎打开手机地图,搜索北海公园附近的餐馆,并选了其中一家用餐. 饭饱之后机机开始反思了,地图后台如何根据自己所在位置查询来查询附近餐馆的呢?苦思冥想了半天,机机想出了个方法:计算所在位置P与北京所有餐馆 的距离,然

TX2017秋招笔试题之geohash编码

问题描述:geohash编码:geohash常用于将二维的经纬度转换为字符串,分为两步:第一步是经纬度的二进制编码,第二步是base32转码. 此题考察纬度的二进制编码:算法对纬度[-90, 90]通过二分法进行无限逼近(取决于所需精度,本题精度为6). 注意,本题进行二分法逼近过程中只采用向下取整来进行二分,针对二分中间值属于右区间.算法举例如下: 针对纬度为80进行二进制编码过程: 1) 区间[-90, 90]进行二分为[-90, 0),[0, 90],成为左右区间,可以确定80为右区间,标

pip install geohash后无法import的解决方法

最近在参加摩拜杯数据挖掘比赛,赛方给的数据里地理位置是用geohash表示的,因此需要安装geohash库进行解析 pip install geohash可以直接安装这个库,可是装好之后import geohash却报错 在网上找了半天,最后解决办法是去python35/Lib/site-packages/目录下,把Geohash文件夹重命名为geohash,然后修改该目录下的__init__.py文件,把from geohash改为from .geohash 然后解决问题

附近的人,附近的卖家(geohash+前缀树)

http://www.cnblogs.com/LBSer/p/3310455.html http://blog.csdn.net/shixiaoguo90/article/details/25313717 MongoDB 中使用geohash  实现地理位置索引 引子 机机是个好动又好学的孩子,平日里就喜欢拿着手机地图点点按按来查询一些好玩的东西.某一天机机到北海公园游玩,肚肚饿了,于是乎打开手机地图,搜索北海公园附近的餐馆,并选了其中一家用餐. 饭饱之后机机开始反思了,地图后台如何根据自己所在