diff options
Diffstat (limited to 'core/src/main/java/org/elasticsearch/common/geo/GeoHashUtils.java')
-rw-r--r-- | core/src/main/java/org/elasticsearch/common/geo/GeoHashUtils.java | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/core/src/main/java/org/elasticsearch/common/geo/GeoHashUtils.java b/core/src/main/java/org/elasticsearch/common/geo/GeoHashUtils.java index 0f1ddcd376..cb31940a49 100644 --- a/core/src/main/java/org/elasticsearch/common/geo/GeoHashUtils.java +++ b/core/src/main/java/org/elasticsearch/common/geo/GeoHashUtils.java @@ -18,13 +18,13 @@ */ package org.elasticsearch.common.geo; -import java.util.ArrayList; -import java.util.Collection; - -import org.apache.lucene.spatial.geopoint.document.GeoPointField; import org.apache.lucene.geo.Rectangle; +import org.apache.lucene.spatial.util.MortonEncoder; import org.apache.lucene.util.BitUtil; +import java.util.ArrayList; +import java.util.Collection; + /** * Utilities for converting to/from the GeoHash standard * @@ -42,19 +42,35 @@ public class GeoHashUtils { /** maximum precision for geohash strings */ public static final int PRECISION = 12; - private static final short MORTON_OFFSET = (GeoPointField.BITS<<1) - (PRECISION*5); + /** number of bits used for quantizing latitude and longitude values */ + public static final short BITS = 31; + /** scaling factors to convert lat/lon into unsigned space */ + private static final double LAT_SCALE = (0x1L<<BITS)/180.0D; + private static final double LON_SCALE = (0x1L<<BITS)/360.0D; + private static final short MORTON_OFFSET = (BITS<<1) - (PRECISION*5); // No instance: private GeoHashUtils() { } + /************************* + * 31 bit encoding utils * + *************************/ + public static long encodeLatLon(final double lat, final double lon) { + long result = MortonEncoder.encode(lat, lon); + if (result == 0xFFFFFFFFFFFFFFFFL) { + return result & 0xC000000000000000L; + } + return result >>> 2; + } + /** * Encode lon/lat to the geohash based long format (lon/lat interleaved, 4 least significant bits = level) */ public static final long longEncode(final double lon, final double lat, final int level) { // shift to appropriate level final short msf = (short)(((12 - level) * 5) + MORTON_OFFSET); - return ((BitUtil.flipFlop(GeoPointField.encodeLatLon(lat, lon)) >>> msf) << 4) | level; + return ((BitUtil.flipFlop(encodeLatLon(lat, lon)) >>> msf) << 4) | level; } /** @@ -120,7 +136,7 @@ public class GeoHashUtils { */ public static final String stringEncode(final double lon, final double lat, final int level) { // convert to geohashlong - final long ghLong = fromMorton(GeoPointField.encodeLatLon(lat, lon), level); + final long ghLong = fromMorton(encodeLatLon(lat, lon), level); return stringEncode(ghLong); } @@ -141,7 +157,7 @@ public class GeoHashUtils { StringBuilder geoHash = new StringBuilder(); short precision = 0; - final short msf = (GeoPointField.BITS<<1)-5; + final short msf = (BITS<<1)-5; long mask = 31L<<msf; do { geoHash.append(BASE_32[(int)((mask & hashedVal)>>>(msf-(precision*5)))]); @@ -303,13 +319,31 @@ public class GeoHashUtils { return neighbors; } + /** decode longitude value from morton encoded geo point */ + public static final double decodeLongitude(final long hash) { + return unscaleLon(BitUtil.deinterleave(hash)); + } + + /** decode latitude value from morton encoded geo point */ + public static final double decodeLatitude(final long hash) { + return unscaleLat(BitUtil.deinterleave(hash >>> 1)); + } + + private static double unscaleLon(final long val) { + return (val / LON_SCALE) - 180; + } + + private static double unscaleLat(final long val) { + return (val / LAT_SCALE) - 90; + } + /** returns the latitude value from the string based geohash */ public static final double decodeLatitude(final String geohash) { - return GeoPointField.decodeLatitude(mortonEncode(geohash)); + return decodeLatitude(mortonEncode(geohash)); } /** returns the latitude value from the string based geohash */ public static final double decodeLongitude(final String geohash) { - return GeoPointField.decodeLongitude(mortonEncode(geohash)); + return decodeLongitude(mortonEncode(geohash)); } } |