Fix north pole overflow error in GeoHashUtils.bbox() (#32891)
Fixes an overflow error in GeoHashUtils.bbox() calculation of a bounding box for geohashes with maximum precision located next to the north pole.
This commit is contained in:
parent
fcf8cadd9a
commit
3973bb4028
|
@ -25,6 +25,8 @@ import org.apache.lucene.util.BitUtil;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import static org.apache.lucene.geo.GeoUtils.MAX_LAT_INCL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utilities for converting to/from the GeoHash standard
|
* Utilities for converting to/from the GeoHash standard
|
||||||
*
|
*
|
||||||
|
@ -48,6 +50,8 @@ public class GeoHashUtils {
|
||||||
private static final double LAT_SCALE = (0x1L<<BITS)/180.0D;
|
private static final double LAT_SCALE = (0x1L<<BITS)/180.0D;
|
||||||
private static final double LON_SCALE = (0x1L<<BITS)/360.0D;
|
private static final double LON_SCALE = (0x1L<<BITS)/360.0D;
|
||||||
private static final short MORTON_OFFSET = (BITS<<1) - (PRECISION*5);
|
private static final short MORTON_OFFSET = (BITS<<1) - (PRECISION*5);
|
||||||
|
/** Bit encoded representation of the latitude of north pole */
|
||||||
|
private static final long MAX_LAT_BITS = (0x1L << (PRECISION * 5 / 2)) - 1;
|
||||||
|
|
||||||
// No instance:
|
// No instance:
|
||||||
private GeoHashUtils() {
|
private GeoHashUtils() {
|
||||||
|
@ -218,12 +222,19 @@ public class GeoHashUtils {
|
||||||
long ghLong = longEncode(geohash, len);
|
long ghLong = longEncode(geohash, len);
|
||||||
// shift away the level
|
// shift away the level
|
||||||
ghLong >>>= 4;
|
ghLong >>>= 4;
|
||||||
// deinterleave and add 1 to lat and lon to get topRight
|
// deinterleave
|
||||||
long lat = BitUtil.deinterleave(ghLong >>> 1) + 1;
|
long lon = BitUtil.deinterleave(ghLong >>> 1);
|
||||||
long lon = BitUtil.deinterleave(ghLong) + 1;
|
long lat = BitUtil.deinterleave(ghLong);
|
||||||
GeoPoint topRight = GeoPoint.fromGeohash(BitUtil.interleave((int)lon, (int)lat) << 4 | len);
|
if (lat < MAX_LAT_BITS) {
|
||||||
|
// add 1 to lat and lon to get topRight
|
||||||
|
GeoPoint topRight = GeoPoint.fromGeohash(BitUtil.interleave((int)(lat + 1), (int)(lon + 1)) << 4 | len);
|
||||||
return new Rectangle(bottomLeft.lat(), topRight.lat(), bottomLeft.lon(), topRight.lon());
|
return new Rectangle(bottomLeft.lat(), topRight.lat(), bottomLeft.lon(), topRight.lon());
|
||||||
|
} else {
|
||||||
|
// We cannot go north of north pole, so just using 90 degrees instead of calculating it using
|
||||||
|
// add 1 to lon to get lon of topRight, we are going to use 90 for lat
|
||||||
|
GeoPoint topRight = GeoPoint.fromGeohash(BitUtil.interleave((int)lat, (int)(lon + 1)) << 4 | len);
|
||||||
|
return new Rectangle(bottomLeft.lat(), MAX_LAT_INCL, bottomLeft.lon(), topRight.lon());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -98,6 +98,11 @@ public class GeoHashTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testNorthPoleBoundingBox() {
|
||||||
|
Rectangle bbox = GeoHashUtils.bbox("zzbxfpgzupbx"); // Bounding box with maximum precision touching north pole
|
||||||
|
assertEquals(90.0, bbox.maxLat, 0.0000001); // Should be 90 degrees
|
||||||
|
}
|
||||||
|
|
||||||
public void testInvalidGeohashes() {
|
public void testInvalidGeohashes() {
|
||||||
IllegalArgumentException ex;
|
IllegalArgumentException ex;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue