GeoHash代码实现–java
package com. sd. leo. geohash;
import java. util. ArrayList;
import java. util. BitSet;
import java. util. HashMap;
public class GeoHash {
public static final double MINLAT = - 90 ;
public static final double MAXLAT = 90 ;
public static final double MINLNG = - 180 ;
public static final double MAXLNG = 180 ;
private static int numbits = 20 ;
private static double minLat;
private static double minLng;
private final static char [ ] digits = { '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' } ;
final static HashMap< Character, Integer> lookup = new HashMap < Character, Integer> ( ) ;
static {
int i = 0 ;
for ( char c : digits) {
lookup. put ( c, i++ ) ;
}
}
public GeoHash ( ) {
setMinLatLng ( ) ;
}
public String encode ( double lat, double lon) {
BitSet latbits = getBits ( lat, - 90 , 90 ) ;
BitSet lonbits = getBits ( lon, - 180 , 180 ) ;
StringBuilder buffer = new StringBuilder ( ) ;
for ( int i = 0 ; i < numbits; i++ ) {
buffer. append ( ( lonbits. get ( i) ) ? '1' : '0' ) ;
buffer. append ( ( latbits. get ( i) ) ? '1' : '0' ) ;
}
String code = base32 ( Long. parseLong ( buffer. toString ( ) , 2 ) ) ;
return code;
}
private BitSet getBits ( double lat, double floor, double ceiling) {
BitSet buffer = new BitSet ( numbits) ;
for ( int i = 0 ; i < numbits; i++ ) {
double mid = ( floor + ceiling) / 2 ;
if ( lat >= mid) {
buffer. set ( i) ;
floor = mid;
} else {
ceiling = mid;
}
}
return buffer;
}
private String base32 ( long i) {
char [ ] buf = new char [ 65 ] ;
int charPos = 64 ;
boolean negative = ( i < 0 ) ;
if ( ! negative) {
i = - i;
}
while ( i <= - 32 ) {
buf[ charPos-- ] = digits[ ( int ) ( - ( i % 32 ) ) ] ;
i /= 32 ;
}
buf[ charPos] = digits[ ( int ) ( - i) ] ;
if ( negative) {
buf[ -- charPos] = '-' ;
}
return new String ( buf, charPos, ( 65 - charPos) ) ;
}
private void setMinLatLng ( ) {
minLat = MAXLAT - MINLAT;
for ( int i = 0 ; i < numbits; i++ ) {
minLat /= 2.0 ;
}
minLng = MAXLNG - MINLNG;
for ( int i = 0 ; i < numbits; i++ ) {
minLng /= 2.0 ;
}
}
public double [ ] decode ( String geohash) {
StringBuilder buffer = new StringBuilder ( ) ;
for ( char c : geohash. toCharArray ( ) ) {
int i = lookup. get ( c) + 32 ;
buffer. append ( Integer. toString ( i, 2 ) . substring ( 1 ) ) ;
}
BitSet lonset = new BitSet ( ) ;
BitSet latset = new BitSet ( ) ;
int j = 0 ;
for ( int i = 0 ; i < numbits * 2 ; i += 2 ) {
boolean isSet = false ;
if ( i < buffer. length ( ) ) {
isSet = buffer. charAt ( i) == '1' ;
}
lonset. set ( j++ , isSet) ;
}
j = 0 ;
for ( int i = 1 ; i < numbits * 2 ; i += 2 ) {
boolean isSet = false ;
if ( i < buffer. length ( ) ) {
isSet = buffer. charAt ( i) == '1' ;
}
latset. set ( j++ , isSet) ;
}
double lon = decode ( lonset, - 180 , 180 ) ;
double lat = decode ( latset, - 90 , 90 ) ;
return new double [ ] { lat, lon} ;
}
private double decode ( BitSet bs, double floor, double ceiling) {
double mid = 0 ;
for ( int i = 0 ; i < bs. length ( ) ; i++ ) {
mid = ( floor + ceiling) / 2 ;
if ( bs. get ( i) ) {
floor = mid;
} else {
ceiling = mid;
}
}
return mid;
}
public ArrayList< String> getArroundGeoHash ( double lat, double lon) {
ArrayList< String> list = new ArrayList < > ( ) ;
double uplat = lat + minLat;
double downLat = lat - minLat;
double leftlng = lon - minLng;
double rightLng = lon + minLng;
String leftUp = encode ( uplat, leftlng) ;
list. add ( leftUp) ;
String leftMid = encode ( lat, leftlng) ;
list. add ( leftMid) ;
String leftDown = encode ( downLat, leftlng) ;
list. add ( leftDown) ;
String midUp = encode ( uplat, lon) ;
list. add ( midUp) ;
String midMid = encode ( lat, lon) ;
list. add ( midMid) ;
String midDown = encode ( downLat, lon) ;
list. add ( midDown) ;
String rightUp = encode ( uplat, rightLng) ;
list. add ( rightUp) ;
String rightMid = encode ( lat, rightLng) ;
list. add ( rightMid) ;
String rightDown = encode ( downLat, rightLng) ;
list. add ( rightDown) ;
return list;
}
public static void main ( String[ ] args) throws Exception {
GeoHash geohash = new GeoHash ( ) ;
String geoHashCode= geohash. encode ( 40.222012 , 116.248283 ) ;
System. out. println ( geoHashCode) ;
ArrayList< String> arroundGeoHash = geohash. getArroundGeoHash ( 40.222012 , 116.248283 ) ;
System. out. println ( arroundGeoHash) ;
double [ ] geo = geohash. decode ( geoHashCode) ;
System. out. println ( geo[ 0 ] + " " + geo[ 1 ] ) ;
}
}