基于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 = ;
    /// <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 = * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / ), ) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / ), ))) * 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 = ,minLat = -,maxLon = ,minLon = -,mid; int hashValue = ;
    int l = hash_string.Length;
    for (int i = ; i < l; i++)
    {
    string code = Convert.ToString(hash_string[i]);
    hashValue = BASE32_CODES_DICT[code]; for (var bits = ; bits >= ; bits--)
    {
    var bit = (hashValue >> bits) & ;
    if (isLon)
    {
    mid = (maxLon + minLon) / ;
    if (bit == )
    {
    minLon = mid;
    }
    else
    {
    maxLon = mid;
    }
    }
    else
    {
    mid = (maxLat + minLat) / ;
    if (bit == )
    {
    minLat = mid;
    }
    else
    {
    maxLat = mid;
    }
    }
    isLon = !isLon;
    }
    }
    return new double[] { minLat, minLon, maxLat, maxLon };
    }
  • 基于以上的代码,在实际应用中基本可完成对附件范围内事物的搜索以及在地图中进行区域标识

geohash-net实现的更多相关文章

  1. 【算法】(查找你附近的人) GeoHash核心原理解析及代码实现

    本文地址 原文地址 分享提纲: 0. 引子 1. 感性认识GeoHash 2. GeoHash算法的步骤 3. GeoHash Base32编码长度与精度 4. GeoHash算法 5. 使用注意点( ...

  2. WebGIS中GeoHash编码的研究和扩展

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 1.1普通地理编码流程 将采集的POI入库后,数据库里保存有 ...

  3. GeoHash原理解析

    GeoHash 核心原理解析       引子 一提到索引,大家脑子里马上浮现出B树索引,因为大量的数据库(如MySQL.oracle.PostgreSQL等)都在使用B树.B树索引本质上是对索引字段 ...

  4. geohash基本原理

    geohash基本原理是将地球理解为一个二维平面,将平面递归分解成更小的子块,每个子块在一定经纬度范围内拥有相同的编码,这种方式简单粗暴,可以满足对小规模的数据进行经纬度的检索 目录: 经纬度常识 认 ...

  5. 【转】GeoHash核心原理解析

    好久没更新过博客了,先转载一篇文章吧. 源地址:http://www.cnblogs.com/LBSer/p/3310455.html 引子 机机是个好动又好学的孩子,平日里就喜欢拿着手机地图点点按按 ...

  6. GeoHash

    查找是我们经常会碰到的问题,以前我做过一个这样的算法,在有序的数列(80万条左右),这批数据是根据维度由小到大排序的,寻找已知数据的位置,并且所相应的运算,由于这个算法要在嵌入式系统中做,如果一次在内 ...

  7. geohash算法原理及实现方式

    1.geohash特点 2.geohash原理 3.geohash的php .python.java.C#实现代码 4.观点讨论 w微博:http://weibo.com/dxl0321 geohas ...

  8. GeoHash核心原理解析

    http://www.cnblogs.com/LBSer/p/3310455.html 引子 机机是个好动又好学的孩子,平日里就喜欢拿着手机地图点点按按来查询一些好玩的东西.某一天机机到北海公园游玩, ...

  9. [转]GeoHash核心原理解析

    原文出处: zhanlijun    引子 机机是个好动又好学的孩子,平日里就喜欢拿着手机地图点点按按来查询一些好玩的东西.某一天机机到北海公园游玩,肚肚饿了,于是乎打开手机地图,搜索北海公园附近的餐 ...

  10. Redis GEO ,GEOHASH,Spatial_index

    https://matt.sh/redis-geo http://antirez.com/latest/0 http://invece.org/ https://github.com/davidmot ...

随机推荐

  1. php+mysql的微信文章发布平台

    如何在微信上发表丰富图文的文章? 最近在新浪云平台上做了一个php+mysql的微信文章发布平台,丫丫说. 在线编辑文章,扫一扫即可分享到微信,发到朋友圈,非常简单! http://yayashuo. ...

  2. valueForKeyPath常用用法

    valueForKeyPath和valueForKey有一些类似,但也有一些不同的地方.这里就简单说一下valueForKeyPath一些不同的地方. 举例来说: 1.valueForKeyPath可 ...

  3. 从service弹出系统级自定义提示框,可在任意页面弹出

    添加权限 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> // 显示 ...

  4. window 下如何安装ghost博客

    1.安装nodejs # Node v0.12.x and v4.2+ LTS - supported 我本地安装的是4.2 安装其他版本可能提示系统不兼容 2.安装mysql 3.安装bower 4 ...

  5. c++类的嵌套(1)

    在一个类的内部定义另一个类或结构体,我们称之为嵌套类(nested class),或者嵌套类型.之所以引入这样一个嵌套类,往往是因为外围类需要使用嵌套类对象作为底层实现,并且该嵌套类只用于外围类的实现 ...

  6. check_pkg函数解析

    函数位置,conf/core,具体代码如下: check_pkg() { # Usage: check_pkg <command> <package> # It means: ...

  7. 基于mongodb的python之增删改查(CRUD)

    1,下载mongodb的python驱动,http://pypi.python.org/pypi/pymongo/,根据操作系统和python平台版本选择相应的egg或exe安装. 2,新建一个py脚 ...

  8. 判断IP地址的类型

    #include <stdio.h> #include <stdlib.h> void main() { ]; int ip_addr; printf("请输入IP地 ...

  9. 用ajax提交form表单及乱码问题

    要求 1. form里是习题和选择的答案包含内容较多,直接用ajax获取页面元素较多,麻烦. 2. 也不能直接用form提交,form提交后会跳转页面,如果出错想在本页面获取错误信息(ajax提交)且 ...

  10. Windows Server 2012 没有远程桌面授权服务器可以提供许可证,远程会话被中断

    今天在登录公司内部的服务器的时候,无法进行远程访问. 弹出错误信息:没有远程桌面授权服务器可以提供许可证,远程会话被中断 经过网上的寻找,原来是server 2012 远程登录只提供120天的使用期限 ...