基于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. C语言程序设计第三次作业

    态度决定一切,无论做什么事情,秉持一个认真的态度,相信一定会让你受益无穷.当提交作业时,如果只是粘贴一下代码和运行结果,那么,你也只是写了一个程序而已,对你自己水平的提升帮助并不大,这次犯的错误或许下 ...

  2. vue吃进去的object已经变了样,不在是原来的!

    直接上代码: class data { public list:number[]; constructor() { this.list=[0,0,0]; } } class methods exten ...

  3. hash表C语言实现

    算法参考<算法导论>第11章散列表.采用链地址法解决冲突. #include <stdio.h> #include <stdlib.h> #include < ...

  4. PAT题库-1064. Complete Binary Search Tree (30)

    1064. Complete Binary Search Tree (30) 时间限制 100 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHE ...

  5. 手把手Maven搭建SpringMVC+Spring+MyBatis框架(超级详细版)

    手把手Maven搭建SpringMVC+Spring+MyBatis框架(超级详细版) SSM(Spring+SpringMVC+Mybatis),目前较为主流的企业级架构方案.标准的MVC设计模式, ...

  6. 主要由顶点容器构成的平面图形类(Shape)——(第一次作业Draw类定义升级)

    // https://github.com/orocos/orocos_kinematics_dynamics/blob/master/orocos_kdl/src/frames.hpp // Vec ...

  7. PSP(16/03/14-16/03/15)

    //整理了自己过去的时间记录文件,最早用电子版记录是15/04/21,依旧断断续续记录到15/11/21,每月至少三次记录,然而自己并没有对数据进行整理,只是纯粹记录,真是浪费了花在上面的时间.期间八 ...

  8. JDK运行.Jar文件的控制台命令是什么

    cd进入jar文件所在目录,执行如下语句: java -jar jar文件名如:java -jar hello.jar

  9. DWR同步异步设置

    做项目时遇到一个问题,使用DWR发现js总是执行完了之后再执行DWR的内容,后来发现然来DWR也有一种同步机制:DWREngine.setAsync(false); 还需要在代码末尾恢复异步DWREn ...

  10. 基于mongodb的java之增删改查(CRUD)

    1,下载驱动https://github.com/mongodb/mongo-java-driver/downloads,导入工程java中 2,建立测试代码 import java.net.Unkn ...