基于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. java filechannel大文件的读写

    java读取大文件 超大文件的几种方法 转自:http://wgslucky.blog.163.com/blog/static/97562532201332324639689/   java 读取一个 ...

  2. vim ---- 一键自动indent的命令

    当用vim拷贝某一段代码到另一个程序的时候,往往indent会有一些问题.. 下面这个强大的命令能够让你一键让代码有很好的格式. gg=G 例子:         

  3. MySQL中的information_schema数据库详解

    information_schema数据库是MySQL自带的,它提供了访问数据库元数据的方式.什么是元数据呢?元数据是关于数据的数据,如数据库名或表名,列的数据类型,或访问权限等.有些时候用于表述该信 ...

  4. ArcGIS二次开发实践— — 遍历ToolBox中的工具!

    在AO中,打开“文件A”的基本流程是: 1.创建对应“文件A”类型的WorkspaceFactory: 2.用WorkspaceFactory创建“文件A”的Workspace,Workspace可以 ...

  5. Container With Most Water -- LeetCode 11

    Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai).  ...

  6. api将一统江湖,再无app

    api的出现,使人们可以通过各种软硬件设备获取所需服务,而不需要安装臃肿的app:今后的智能设备将不再依赖软件.操作系统和硬件,或许一台51单片机都可以提供给用户所需信息.当然连名字都可以简单到不叫a ...

  7. git 较基础命令

    还需要进一步了解git的组织形式: git clone *.git 下载下来以git方式管理 如果直接下载压缩包做不到 git branch 分支相关命令 git checkout 可以换分支 git ...

  8. Python-Day3知识点——深浅拷贝、函数基本定义、内置函数

    一.深浅拷贝 import copy #浅拷贝 n1={'k1':'wu','k2':123,'k3':['carl',852]} n2=n1 n3=copy.copy(n1) print(id(n1 ...

  9. Chapter 3.GDI/DirectDraw Internal Data Structures

    说明,在这里决定跳过第二章,实在是因为里面涉及的内容太理论,对我而言又太艰深 3.1 HANDLES AND OBJECT-ORIRNTED PROGRAMMING In normal object- ...

  10. 图片轮播(bootstrap)与 圆角搜索框(纯css)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...