坐标hash编码与解码

public class GeoHashKit {

 private static char[] _base32 = { '0', '1', '2', '3', '4', '5', '6', '7',
  '8', '9', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n',
  'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };

 private final static Map<Character, Integer> _decodemap = new HashMap<Character, Integer>();
 static {
  int sz = _base32.length;
  for (int i = 0; i < sz; i++) {
   _decodemap.put(_base32[i], i);
     }
 }
 
 private static int precision = 12;
 private static int[] bits = { 16, 8, 4, 2, 1 };
 
 public static String encode(double latitude, double longitude) {
  double[] lat_interval = { -90.0, 90.0 };
  double[] lon_interval = { -180.0, 180.0 };

  StringBuilder geohash = new StringBuilder();
  boolean is_even = true;
  int bit = 0, ch = 0;

  while (geohash.length() < precision) {
   double mid = 0.0;
   if (is_even) {
    mid = (lon_interval[0] + lon_interval[1]) / 2;
    if (longitude > mid) {
     ch |= bits[bit];
     lon_interval[0] = mid;
    } else {
     lon_interval[1] = mid;
    }

   } else {
    mid = (lat_interval[0] + lat_interval[1]) / 2;
    if (latitude > mid) {
     ch |= bits[bit];
     lat_interval[0] = mid;
    } else {
     lat_interval[1] = mid;
    }
   }

   is_even = is_even ? false : true;

   if (bit < 4) {
    bit++;
   } else {
    geohash.append(_base32[ch]);
    bit = 0;
    ch = 0;
   }
  }

  return geohash.toString();
 }

 public static double[] decode(String geohash) {
  double[] ge = decode_exactly(geohash);
  double lat, lon, lat_err, lon_err;
  lat = ge[0];
  lon = ge[1];
  lat_err = ge[2];
  lon_err = ge[3];

  double lat_precision = Math.max(1, Math.round(-Math.log10(lat_err))) - 1;
  double lon_precision = Math.max(1, Math.round(-Math.log10(lon_err))) - 1;

  lat = getPrecision(lat, lat_precision);
  lon = getPrecision(lon, lon_precision);

  return new double[] { lat, lon };
 }

 public static double[] decode_exactly(String geohash) {
  double[] lat_interval = { -90.0, 90.0 };
  double[] lon_interval = { -180.0, 180.0 };

  double lat_err = 90.0;
  double lon_err = 180.0;
  boolean is_even = true;
  int sz = geohash.length();
  int bsz = bits.length;
  double latitude, longitude;
  for (int i = 0; i < sz; i++) {

   int cd = _decodemap.get(geohash.charAt(i));

   for (int z = 0; z < bsz; z++) {
    int mask = bits[z];
    if (is_even) {
     lon_err /= 2;
     if ((cd & mask) != 0) {
      lon_interval[0] = (lon_interval[0] + lon_interval[1]) / 2;
     } else {
      lon_interval[1] = (lon_interval[0] + lon_interval[1]) / 2;
     }

    } else {
     lat_err /= 2;

     if ((cd & mask) != 0) {
      lat_interval[0] = (lat_interval[0] + lat_interval[1]) / 2;
     } else {
      lat_interval[1] = (lat_interval[0] + lat_interval[1]) / 2;
     }
    }
    is_even = is_even ? false : true;
   }

  }
  latitude = (lat_interval[0] + lat_interval[1]) / 2;
  longitude = (lon_interval[0] + lon_interval[1]) / 2;

  return new double[] { latitude, longitude, lat_err, lon_err };
 }

 static double getPrecision(double x, double precision) {
  double base = Math.pow(10, -precision);
  double diff = x % base;
  return x - diff;
 }
}

转载于:https://www.cnblogs.com/caowei-it/p/4145778.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值