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;
    }

应用场景

  • 遍历一个区域内的指定精度的经纬度
  • 二维地址的降维与变形,方便做地址与经纬度的映射关系

你可能感兴趣的:(ch.hsr.geohash包使用)