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

本文实例介绍了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));
 } 

}

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

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索java
, Geohash
经纬度坐标
geohash 经纬度、geohash转经纬度 在线、经纬度转geohash、经纬度转化、经纬度转化十进制坐标,以便于您获取更多的相关知识。

时间: 2024-12-17 18:25:55

Java将GeoHash转化为对应的经纬度坐标实例代码_java的相关文章

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

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

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

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

java 装饰模式(Decorator Pattern)详解及实例代码_java

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能. 我们通过下面的实例来演示装饰器模式的使用.其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类. 实现 我们将创建一个 Shape 接口和实现了 Shape 接口的实体类.然后我们创建一个实现了 Shape 接口的抽象装饰类Sha

JAVA中使用FTPClient实现文件上传下载实例代码_java

在java程序开发中,ftp用的比较多,经常打交道,比如说向FTP服务器上传文件.下载文件,本文给大家介绍如何利用jakarta commons中的FTPClient(在commons-net包中)实现上传下载文件. 一.上传文件 原理就不介绍了,大家直接看代码吧 /** * Description: 向FTP服务器上传文件 * @Version1.0 Jul 27, 2008 4:31:09 PM by 崔红保(cuihongbao@d-heaven.com)创建 * @param url F

java实现合并两个已经排序的列表实例代码_java

相对于C++来说,Java的最大特点之一就是没有令人困惑的指针,但是我们不可否认,在某些特定的情境下,指针确实算的上一把利刃.虽然Java中没有明确定义出指针,但是由于类的思想,我们可以使用class来实现指针的操作.小二,上栗子-----合并两个已经排序的列表,输出合并后列表的头结点,且合并后的列表中的元素是有序的. 需要时刻铭记于心的:在Java中,列表的一个节点其实就是某个类实例化的一个对象. 示例代码如下: 复制代码 代码如下: package DecemberOf2013; class

java 反射和动态代理详解及实例代码_java

一.java中的反射 1.通过反射加载类的属性和方法实例代码: /** * java.lang.Class 是反射的源头 * 我们创建了一个类,通过编译(javac.exe)生成对应的class文件,之后我们通过java.exe加载(jvm的类加载器加载)此class文件 * 此class文件加载到内存后,就是一个运行时类,存在缓存区,这个运行时类本事就是一个Class的实例 * 每一个运行时类只加载一次, */ Class<StudentExam> clazz = StudentExam.c

Java 时间转换的实例代码_java

Java 时间转换的实例代码 import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * Created by Edward on 2016/6/30. */ public class TimeUtil { /** * 将 1467341232351 转换为 指定格式 "yyyy-MM-dd HH:mm:ss.

使用Java和WebSocket实现网页聊天室实例代码_java

在没介绍正文之前,先给大家介绍下websocket的背景和原理: 背景 在浏览器中通过http仅能实现单向的通信,comet可以一定程度上模拟双向通信,但效率较低,并需要服务器有较好的支持; flash中的socket和xmlsocket可以实现真正的双向通信,通过 flex ajax bridge,可以在javascript中使用这两项功能. 可以预见,如果websocket一旦在浏览器中得到实现,将会替代上面两项技术,得到广泛的使用.面对这种状况,HTML5定义了WebSocket协议,能更

java Arrays类详解及实例代码_java

最近做项目 用到Arrays 类,这里整理下,希望大家能够掌握Arrays . 1.Arrays类概述   针对数组进行操作的工具类.   提供了排序,查找等功能. 2.成员方法   public static String toString(int[] a)   public static void sort(int[] a)   public static int binarySearch(int[] a,int value) package com; import java.util.Ar