summaryrefslogtreecommitdiff
path: root/core/src/main/java/org/elasticsearch/common/geo/GeoHashUtils.java
diff options
context:
space:
mode:
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.java54
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));
}
}