Java将GeoHash转化为对应的经纬度坐标实例代码

本文实例介绍了JAVA实现将GeoHash转化为对应的经纬度坐标的详细代码,分享给大家供大家参考,具体内容如下

package com.lulei.geo; 

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List; 

import com.lulei.geo.bean.LocationBean;
import com.lulei.util.JsonUtil; 

public class GeoHash {
 private LocationBean location;
 /**
  * 1 2500km;2 630km;3 78km;4 30km
  * 5 2.4km; 6 610m; 7 76m; 8 19m
  */
 private int hashLength = 8; //经纬度转化为geohash长度
 private int latLength = 20; //纬度转化为二进制长度
 private int lngLength = 20; //经度转化为二进制长度 

 private double minLat;//每格纬度的单位大小
 private double minLng;//每个经度的单位大小
 private static final char[] CHARS = {'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 static HashMap<Character, Integer> CHARSMAP; 

 static {
  CHARSMAP = new HashMap<Character, Integer>();
  for (int i = 0; i < CHARS.length; i++) {
   CHARSMAP.put(CHARS[i], i);
  }
 } 

 public GeoHash(double lat, double lng) {
  location = new LocationBean(lat, lng);
  setMinLatLng();
 } 

 public int gethashLength() {
  return hashLength;
 } 

 /**
  * @Author:lulei
  * @Description: 设置经纬度的最小单位
  */
 private void setMinLatLng() {
  minLat = LocationBean.MAXLAT - LocationBean.MINLAT;
  for (int i = 0; i < latLength; i++) {
   minLat /= 2.0;
  }
  minLng = LocationBean.MAXLNG - LocationBean.MINLNG;
  for (int i = 0; i < lngLength; i++) {
   minLng /= 2.0;
  }
 } 

 /**
  * @return
  * @Author:lulei
  * @Description: 求所在坐标点及周围点组成的九个
  */
 public List<String> getGeoHashBase32For9() {
  double leftLat = location.getLat() - minLat;
  double rightLat = location.getLat() + minLat;
  double upLng = location.getLng() - minLng;
  double downLng = location.getLng() + minLng;
  List<String> base32For9 = new ArrayList<String>();
  //左侧从上到下 3个
  String leftUp = getGeoHashBase32(leftLat, upLng);
  if (!(leftUp == null || "".equals(leftUp))) {
   base32For9.add(leftUp);
  }
  String leftMid = getGeoHashBase32(leftLat, location.getLng());
  if (!(leftMid == null || "".equals(leftMid))) {
   base32For9.add(leftMid);
  }
  String leftDown = getGeoHashBase32(leftLat, downLng);
  if (!(leftDown == null || "".equals(leftDown))) {
   base32For9.add(leftDown);
  }
  //中间从上到下 3个
  String midUp = getGeoHashBase32(location.getLat(), upLng);
  if (!(midUp == null || "".equals(midUp))) {
   base32For9.add(midUp);
  }
  String midMid = getGeoHashBase32(location.getLat(), location.getLng());
  if (!(midMid == null || "".equals(midMid))) {
   base32For9.add(midMid);
  }
  String midDown = getGeoHashBase32(location.getLat(), downLng);
  if (!(midDown == null || "".equals(midDown))) {
   base32For9.add(midDown);
  }
  //右侧从上到下 3个
  String rightUp = getGeoHashBase32(rightLat, upLng);
  if (!(rightUp == null || "".equals(rightUp))) {
   base32For9.add(rightUp);
  }
  String rightMid = getGeoHashBase32(rightLat, location.getLng());
  if (!(rightMid == null || "".equals(rightMid))) {
   base32For9.add(rightMid);
  }
  String rightDown = getGeoHashBase32(rightLat, downLng);
  if (!(rightDown == null || "".equals(rightDown))) {
   base32For9.add(rightDown);
  }
  return base32For9;
 } 

 /**
  * @param length
  * @return
  * @Author:lulei
  * @Description: 设置经纬度转化为geohash长度
  */
 public boolean sethashLength(int length) {
  if (length < 1) {
   return false;
  }
  hashLength = length;
  latLength = (length * 5) / 2;
  if (length % 2 == 0) {
   lngLength = latLength;
  } else {
   lngLength = latLength + 1;
  }
  setMinLatLng();
  return true;
 } 

 /**
  * @return
  * @Author:lulei
  * @Description: 获取经纬度的base32字符串
  */
 public String getGeoHashBase32() {
  return getGeoHashBase32(location.getLat(), location.getLng());
 } 

 /**
  * @param lat
  * @param lng
  * @return
  * @Author:lulei
  * @Description: 获取经纬度的base32字符串
  */
 private String getGeoHashBase32(double lat, double lng) {
  boolean[] bools = getGeoBinary(lat, lng);
  if (bools == null) {
   return null;
  }
  StringBuffer sb = new StringBuffer();
  for (int i = 0; i < bools.length; i = i + 5) {
   boolean[] base32 = new boolean[5];
   for (int j = 0; j < 5; j++) {
    base32[j] = bools[i + j];
   }
   char cha = getBase32Char(base32);
   if (' ' == cha) {
    return null;
   }
   sb.append(cha);
  }
  return sb.toString();
 } 

 /**
  * @param base32
  * @return
  * @Author:lulei
  * @Description: 将五位二进制转化为base32
  */
 private char getBase32Char(boolean[] base32) {
  if (base32 == null || base32.length != 5) {
   return ' ';
  }
  int num = 0;
  for (boolean bool : base32) {
   num <<= 1;
   if (bool) {
    num += 1;
   }
  }
  return CHARS[num % CHARS.length];
 } 

 /**
  * @param i
  * @return
  * @Author:lulei
  * @Description: 将数字转化为二进制字符串
  */
 private String getBase32BinaryString(int i) {
  if (i < 0 || i > 31) {
   return null;
  }
  String str = Integer.toBinaryString(i + 32);
  return str.substring(1);
 } 

 /**
  * @param geoHash
  * @return
  * @Author:lulei
  * @Description: 将geoHash转化为二进制字符串
  */
 private String getGeoHashBinaryString(String geoHash) {
  if (geoHash == null || "".equals(geoHash)) {
   return null;
  }
  StringBuffer sb = new StringBuffer();
  for (int i = 0; i < geoHash.length(); i++) {
   char c = geoHash.charAt(i);
   if (CHARSMAP.containsKey(c)) {
    String cStr = getBase32BinaryString(CHARSMAP.get(c));
    if (cStr != null) {
     sb.append(cStr);
    }
   }
  }
  return sb.toString();
 } 

 /**
  * @param geoHash
  * @return
  * @Author:lulei
  * @Description: 返回geoHash 对应的坐标
  */
 public LocationBean getLocation(String geoHash) {
  String geoHashBinaryStr = getGeoHashBinaryString(geoHash);
  if (geoHashBinaryStr == null) {
   return null;
  }
  StringBuffer lat = new StringBuffer();
  StringBuffer lng = new StringBuffer();
  for (int i = 0; i < geoHashBinaryStr.length(); i++) {
   if (i % 2 != 0) {
    lat.append(geoHashBinaryStr.charAt(i));
   } else {
    lng.append(geoHashBinaryStr.charAt(i));
   }
  }
  double latValue = getGeoHashMid(lat.toString(), LocationBean.MINLAT, LocationBean.MAXLAT);
  double lngValue = getGeoHashMid(lng.toString(), LocationBean.MINLNG, LocationBean.MAXLNG);
  LocationBean location = new LocationBean(latValue, lngValue);
  location.setGeoHash(geoHash);
  return location;
 } 

 /**
  * @param binaryStr
  * @param min
  * @param max
  * @return
  * @Author:lulei
  * @Description: 返回二进制对应的中间值
  */
 private double getGeoHashMid(String binaryStr, double min, double max) {
  if (binaryStr == null || binaryStr.length() < 1) {
   return (min + max) / 2.0;
  }
  if (binaryStr.charAt(0) == '1') {
   return getGeoHashMid(binaryStr.substring(1), (min + max) / 2.0, max);
  } else {
   return getGeoHashMid(binaryStr.substring(1), min, (min + max) / 2.0);
  }
 } 

 /**
  * @param lat
  * @param lng
  * @return
  * @Author:lulei
  * @Description: 获取坐标的geo二进制字符串
  */
 private boolean[] getGeoBinary(double lat, double lng) {
  boolean[] latArray = getHashArray(lat, LocationBean.MINLAT, LocationBean.MAXLAT, latLength);
  boolean[] lngArray = getHashArray(lng, LocationBean.MINLNG, LocationBean.MAXLNG, lngLength);
  return merge(latArray, lngArray);
 } 

 /**
  * @param latArray
  * @param lngArray
  * @return
  * @Author:lulei
  * @Description: 合并经纬度二进制
  */
 private boolean[] merge(boolean[] latArray, boolean[] lngArray) {
  if (latArray == null || lngArray == null) {
   return null;
  }
  boolean[] result = new boolean[lngArray.length + latArray.length];
  Arrays.fill(result, false);
  for (int i = 0; i < lngArray.length; i++) {
   result[2 * i] = lngArray[i];
  }
  for (int i = 0; i < latArray.length; i++) {
   result[2 * i + 1] = latArray[i];
  }
  return result;
 } 

 /**
  * @param value
  * @param min
  * @param max
  * @return
  * @Author:lulei
  * @Description: 将数字转化为geohash二进制字符串
  */
 private boolean[] getHashArray(double value, double min, double max, int length) {
  if (value < min || value > max) {
   return null;
  }
  if (length < 1) {
   return null;
  }
  boolean[] result = new boolean[length];
  for (int i = 0; i < length; i++) {
   double mid = (min + max) / 2.0;
   if (value > mid) {
    result[i] = true;
    min = mid;
   } else {
    result[i] = false;
    max = mid;
   }
  }
  return result;
 } 

 public static void main(String[] args) {
  // TODO Auto-generated method stub
  GeoHash g = new GeoHash(40.221227, 116.24875);
  String geoHash = g.getGeoHashBase32();
  System.out.println(geoHash);
  LocationBean bean = g.getLocation(geoHash);
  System.out.println(JsonUtil.parseJson(bean));
  System.out.println(new GeoHash(bean.getLat(), bean.getLng()).getGeoHashBase32());
  System.out.println(DistanceUtil.getDistance(bean.getLat(), bean.getLng(), bean.getLat() - g.minLat, bean.getLng() - g.minLng));
 } 

}

以上就是本文的详细内容,希望对大家的学习有所帮助。

(0)

相关推荐

  • JAVA实现空间索引编码——GeoHash的示例

    之前自己在做基于Lucene的内容检索过程中,了解到Lucene可以实现对文本信息,数值信息的内容检索,对于空间距离好像并为为源码中实现:最近半年自己接触到Solr,里面有一个空间距离检索(经纬度),最近对其中的实现做了下学习,了解到在实现空间距离检索的有一个比较常用的技术--GeoHash,下面就介绍下GeoHash. GeoHash特点 GeoHash用一个字符串表示经度和纬度两个坐标,比如我现在所在位置的GeoHash值为 wx4sv61q: GeoHash标识的并不是一个点,而是一个区域

  • Java将GeoHash转化为对应的经纬度坐标实例代码

    本文实例介绍了JAVA实现将GeoHash转化为对应的经纬度坐标的详细代码,分享给大家供大家参考,具体内容如下 package com.lulei.geo; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import com.lulei.geo.bean.LocationBean; import com.lulei.util.JsonUti

  • Java利用openoffice将doc、docx转为pdf实例代码

    本文研究的主要是Java编程利用openoffice将doc.docx转为pdf的实现代码,具体如下. 1. 需要用的软件 OpenOffice , JodConverter 2.启动OpenOffice的服务 我到网上查如何利用OpenOffice进行转码的时候,都是需要先用cmd启动一个soffice服务,启动的命令是:soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;". 但是实际上,对于我的项目,进行转

  • Java编程一维数组转换成二维数组实例代码

    简介:由于经常在使用矩阵进行计算时,会首先将一维数组转为二维数组.因此,在这里记录一下,也希望对他人有帮助. 实例代码: package deal; public class ArryTest { public static void main(String[] args) { //创建一个一维数组 0,1,2,3...,10 double [] c= new double[10]; for (int i = 0; i < c.length; i++) { c[i]=i; } double[][

  • Java程序打包成带参数的jar文件实例代码

    这里我们通过Apache Commons CLI来完成目标功能,废话不多说直接上代码 所需的maven依赖 <dependency> <groupId>commons-cli</groupId> <artifactId>commons-cli</artifactId> <version>1.4</version> </dependency> 这里我们贴出主类代码 Options opts = new Optio

  • java 将byte中的有效长度转换为String的实例代码

    一般的我们使用byte接收读取到的数据,若数据没有达到byte定义的大小时,我们直接将byte转换为String则会出现乱码的情况,在这种情况下应该基于read的返回值来转换byte,否则将产生乱码的情况, 下面是一个简单的示例: package com.javaio.myinputstream; public class MyConsole { public static void main(String argv[]) throws Exception { System.out.printl

  • Java 从网上下载文件的几种方式实例代码详解

    废话不多说了,直接给大家贴代码了,具体代码如下所示: package com.github.pandafang.tool; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.chan

  • Java与WebUploader相结合实现文件上传功能(实例代码)

    之前自己写小项目的时候也碰到过文件上传的问题,没有找到很好的解决方案.虽然之前网找各种解决方案的时候也看到过WebUploader,但没有进一步深究.这次稍微深入了解了些,这里也做个小结. 简单的文件和普通数据上传并保存 jsp页面: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE h

  • java实现连接mysql数据库单元测试查询数据的实例代码

    1.按照javaweb项目的要求逐步建立搭建起机构,具体的类包有:model .db.dao.test; 具体的架构详见下图: 2.根据搭建的项目架构新建数据库test和数据库表t_userinfo并且添加对应的测试数据; (这里我使用的是绿色版的数据库,具体的下载地址:http://pan.baidu.com/s/1mg88YAc) 具体的建立数据库操作详见下图: 3.编写包中的各种类代码,具体参考代码如下: UserInfo.java /** * FileName: UserInfo.jav

  • Java编程基于快速排序的三个算法题实例代码

    快速排序原理简介 快速排序是我们之前学习的冒泡排序的升级,他们都属于交换类排序,都是采用不断的比较和移动来实现排序的.快速排序是一种非常高效的排序算法,它的实现,增大了记录的比较和移动的距离,将关键字较大的记录从前面直接移动到后面,关键字较小的记录从后面直接移动到前面,从而减少了总的比较次数和移动次数.同时采用"分而治之"的思想,把大的拆分为小的,小的拆分为更小的,其原理如下:对于给定的一组记录,选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,

  • java根据开始时间结束时间计算中间间隔日期的实例代码

    具体代码如下所述: import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; public class Test { public static List<String> findDates(String stime,

随机推荐