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.Collection;
|
||||
|
||||
import static org.apache.lucene.geo.GeoUtils.MAX_LAT_INCL;
|
||||
|
||||
/**
|
||||
* 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 LON_SCALE = (0x1L<<BITS)/360.0D;
|
||||
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:
|
||||
private GeoHashUtils() {
|
||||
|
@ -218,12 +222,19 @@ public class GeoHashUtils {
|
|||
long ghLong = longEncode(geohash, len);
|
||||
// shift away the level
|
||||
ghLong >>>= 4;
|
||||
// deinterleave and add 1 to lat and lon to get topRight
|
||||
long lat = BitUtil.deinterleave(ghLong >>> 1) + 1;
|
||||
long lon = BitUtil.deinterleave(ghLong) + 1;
|
||||
GeoPoint topRight = GeoPoint.fromGeohash(BitUtil.interleave((int)lon, (int)lat) << 4 | len);
|
||||
|
||||
return new Rectangle(bottomLeft.lat(), topRight.lat(), bottomLeft.lon(), topRight.lon());
|
||||
// deinterleave
|
||||
long lon = BitUtil.deinterleave(ghLong >>> 1);
|
||||
long lat = BitUtil.deinterleave(ghLong);
|
||||
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());
|
||||
} 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() {
|
||||
IllegalArgumentException ex;
|
||||
|
||||
|
|
Loading…
Reference in New Issue