ch.hsr.geohash包使用

ch.hsr.geohash 是开源项目,可以让你在java项目中方便的进行经纬度的geohash相关计算,如果您对geohash比较陌生,可以看之前的geohash的简明介绍文章。

本文涉及到点

  • ch.hsr.geohash包涉及模块
  • ch.hsr.geohash包涉及的一些算法
  • ch.hsr.geohash包涉及的应用场景

模块

geohash包涉及类很少,基本就是围绕生成、解析geohash的工作展开

:. 
│  BoundingBox.java # 边界盒型类
│  GeoHash.java # geohash的主要计算操作类
│  WGS84Point.java # WGS84的坐标点类
│
├─queries
│      GeoHashBoundingBoxQuery.java # geohash盒型查询
│      GeoHashCircleQuery.java # geohash循环查询
│      GeoHashQuery.java # geohash查询
│
└─util
        BoundingBoxGeoHashIterator.java #盒型geohash迭代器
        BoundingBoxSampler.java #
        GeoHashSizeTable.java # geohash的尺寸表
        LongUtil.java # 
        TwoGeoHashBoundingBox.java # 使用两个geohash值构建一个外接盒型
        VincentyGeodesy.java # VicentyGeo绘制算法

BoundingBox.java

边界盒型类,我自己这样命名的,该类主要构造方法有三个,但功能都是近似的,使用坐标构建出一个矩形(类似于geohash,但是表达方式不一样,geohash是利用矩形中心点坐标来描述矩形、BoundingBox使用“左下”和“右上”两个点来描述矩形)

# 构造方法
  public BoundingBox(WGS84Point p1, WGS84Point p2) {
        this(p1.getLatitude(), p2.getLatitude(), p1.getLongitude(), p2.getLongitude());
    }

    public BoundingBox(double y1, double y2, double x1, double x2) {
        this.minLon = Math.min(x1, x2);
        this.maxLon = Math.max(x1, x2);
        this.minLat = Math.min(y1, y2);
        this.maxLat = Math.max(y1, y2);
    }

    public BoundingBox(BoundingBox that) {
        this(that.minLat, that.maxLat, that.minLon, that.maxLon);
    }

该类具有一些工具方法,比如

  • 判断一个点是否在该矩形内
  • 判断两个矩形是否有交集
  • 获取矩形的中心点
  • 把一个矩形填充到另外矩形中

GeoHash.java

geohash的核心类,使用者可以通过该类进行经纬度与geohash的转换
生成geohash对象有三种形式(静态工厂方法)

  • double类型经纬度值+字符串精度级别
  • double类型经纬度值+bit位数的精度级别
  • 二进制字符串
  • geohash字符串
  • 用long表示的二进制数+标识位
# double类型经纬度值+字符串精度级别
public static GeoHash withCharacterPrecision(double latitude, double longitude, int numberOfCharacters)
# double类型经纬度值+bit位数的精度级别
public static GeoHash withBitPrecision(double latitude, double longitude, int numberOfBits)
# 二进制字符串 
public static GeoHash fromBinaryString(String binaryString)
# geohash字符串
public static GeoHash fromGeohashString(String geohash) 
# 用long表示的二进制数+标识位
public static GeoHash fromLongValue(long hashVal, int significantBits)

为什么geohash的精度要区分使用字符串标识和二进制标识呢?这个可以看geohash的简明介绍里面的关于geohash值的计算。
在静态工厂方法中,我们也可以看到,关于精度,geohash字符形式的精度只有12位,二进制的精度是60位。因为5个二进制位对应一个Base32中字符(geohash特殊的Base32映射字面量,非标准Base32)

WGS84Point.java

涉及算法

列举其中比较关键或者实现巧妙的方法

  • 把二进数根据奇偶位分解(geohash逆计算中二进制反解经纬度)
// 方法标记:ch.hsr.geohash.GeoHash#extractEverySecondBit(long copyOfBits, int numberOfBits)
    public static final long FIRST_BIT_FLAGGED = 0x8000000000000000L;// 如常量名,BIT的首位校验标识,用于判断二进制数首位
    private long extractEverySecondBit(long copyOfBits, int numberOfBits) {

        long value = 0;  // 奇数位或偶数位的保存值
        for (int i = 0; i < numberOfBits; i++) {// 遍历geohash二进制数值
            if ((copyOfBits & FIRST_BIT_FLAGGED) == FIRST_BIT_FLAGGED) {
                value |= 0x1;//如果解析当前geohash二进制首位为1,则value当前二进制位置为1
            }
            value <<= 1;// 保存值左移1位
            copyOfBits <<= 2;// geohash值左移两位、首位变为下一个偶数位
        }
        value >>>= 1;// 结束时,无符号右移一位,取消最后的保存值左移一位(取消最后value<<=1)
        return value;
    }

应用场景

  • 遍历一个区域内的指定精度的经纬度
  • 二维地址的降维与变形,方便做地址与经纬度的映射关系
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • GeoHash算法 涉及到地图的内容,基本都会遇到搜索附近的功能,比如附近的人、附近的店铺等。要实现这样的功能,我...
    小苏c阅读 2,036评论 0 2
  • 1. 引言 GeoHash本质上是空间索引的一种方式,其基本原理是将地球理解为一个二维平面,将平面递归分解成更小的...
    renzehello阅读 38,761评论 1 17
  • 1.场景 随着智能手机和传感器技术的发展,LBS(Location based service)类的应用也逐渐多了...
    Daniel_adu阅读 11,495评论 3 13
  • 狂歌 五年仿佛是一眨眼,一个小小的女孩,即将迈进初中。小学很小,但在小学度过的时光却让我难以忘怀。毕竟小学只有一次...
    scentforever阅读 376评论 0 2
  • 我两年前就申请了自媒体平台,最早是申请今日头条,因为是第一次,所以比较坎坷。申请了两次,后来自媒体平台都是一次过。...
    秦志强阅读 683评论 0 2