LUCENE-7130: fold optimizations from LatLonPoint to GeoPointField

This commit is contained in:
Robert Muir 2016-03-22 17:47:09 -04:00
parent 1e5f74a02b
commit 5385c8d92f
3 changed files with 34 additions and 9 deletions

View File

@ -104,12 +104,12 @@ final class LatLonPointDistanceQuery extends Query {
// compute a maximum partial haversin: unless our box is crazy, we can use this bound
// to reject edge cases faster in matches()
final double minPartialDistance;
final double maxPartialDistance;
if (box.maxLon - longitude < 90 && longitude - box.minLon < 90) {
minPartialDistance = Math.max(SloppyMath.haversinSortKey(latitude, longitude, latitude, box.maxLon),
maxPartialDistance = Math.max(SloppyMath.haversinSortKey(latitude, longitude, latitude, box.maxLon),
SloppyMath.haversinSortKey(latitude, longitude, box.maxLat, longitude));
} else {
minPartialDistance = Double.POSITIVE_INFINITY;
maxPartialDistance = Double.POSITIVE_INFINITY;
}
return new ConstantScoreWeight(this) {
@ -235,7 +235,7 @@ final class LatLonPointDistanceQuery extends Query {
// first check the partial distance, if its more than that, it can't be <= radiusMeters
double h1 = SloppyMath.haversinSortKey(latitude, longitude, docLatitude, docLongitude);
if (h1 > minPartialDistance) {
if (h1 > maxPartialDistance) {
continue;
}

View File

@ -29,11 +29,23 @@ final class GeoPointDistanceQueryImpl extends GeoPointInBBoxQueryImpl {
private final GeoPointDistanceQuery distanceQuery;
private final double centerLon;
// optimization, maximum partial haversin needed to be a candidate
private final double maxPartialDistance;
GeoPointDistanceQueryImpl(final String field, final TermEncoding termEncoding, final GeoPointDistanceQuery q,
final double centerLonUnwrapped, final GeoRect bbox) {
super(field, termEncoding, bbox.minLat, bbox.maxLat, bbox.minLon, bbox.maxLon);
distanceQuery = q;
centerLon = centerLonUnwrapped;
// unless our box is crazy, we can use this bound
// to reject edge cases faster in postFilter()
if (bbox.maxLon - centerLon < 90 && centerLon - bbox.minLon < 90) {
maxPartialDistance = Math.max(SloppyMath.haversinSortKey(distanceQuery.centerLat, centerLon, distanceQuery.centerLat, bbox.maxLon),
SloppyMath.haversinSortKey(distanceQuery.centerLat, centerLon, bbox.maxLat, centerLon));
} else {
maxPartialDistance = Double.POSITIVE_INFINITY;
}
}
@Override
@ -65,8 +77,7 @@ final class GeoPointDistanceQueryImpl extends GeoPointInBBoxQueryImpl {
@Override
protected boolean cellWithin(final double minLat, final double maxLat, final double minLon, final double maxLon) {
// TODO: we call cellCrosses because of how the termsEnum logic works, helps us avoid some haversin() calls here.
if (cellCrosses(minLat, maxLat, minLon, maxLon) && maxLon - centerLon < 90 && centerLon - minLon < 90 &&
if (maxLon - centerLon < 90 && centerLon - minLon < 90 &&
SloppyMath.haversinMeters(distanceQuery.centerLat, centerLon, minLat, minLon) <= distanceQuery.radiusMeters &&
SloppyMath.haversinMeters(distanceQuery.centerLat, centerLon, minLat, maxLon) <= distanceQuery.radiusMeters &&
SloppyMath.haversinMeters(distanceQuery.centerLat, centerLon, maxLat, minLon) <= distanceQuery.radiusMeters &&
@ -90,7 +101,19 @@ final class GeoPointDistanceQueryImpl extends GeoPointInBBoxQueryImpl {
*/
@Override
protected boolean postFilter(final double lat, final double lon) {
return SloppyMath.haversinMeters(distanceQuery.centerLat, centerLon, lat, lon) <= distanceQuery.radiusMeters;
// check bbox
if (lat < minLat || lat > maxLat || lon < minLon || lon > maxLon) {
return false;
}
// first check the partial distance, if its more than that, it can't be <= radiusMeters
double h1 = SloppyMath.haversinSortKey(distanceQuery.centerLat, centerLon, lat, lon);
if (h1 > maxPartialDistance) {
return false;
}
// fully confirm with part 2:
return SloppyMath.haversinMeters(h1) <= distanceQuery.radiusMeters;
}
}

View File

@ -99,8 +99,10 @@ final class GeoPointPrefixTermsEnum extends GeoPointTermsEnum {
maxLon = mortonUnhashLon(currEnd);
maxLat = mortonUnhashLat(currEnd);
isWithin = false;
// within or a boundary
if ((isWithin = within(minLat, maxLat, minLon, maxLon) == true) || boundary(minLat, maxLat, minLon, maxLon) == true) {
if (boundary(minLat, maxLat, minLon, maxLon) == true) {
isWithin = within(minLat, maxLat, minLon, maxLon);
final int m;
if (isWithin == false || (m = shift % GeoPointField.PRECISION_STEP) == 0) {
setNextRange(isWithin == false);