diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointDistanceQuery.java b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointDistanceQuery.java index 5e7a04e7657..bba92b3e854 100644 --- a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointDistanceQuery.java +++ b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointDistanceQuery.java @@ -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; } diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointDistanceQueryImpl.java b/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointDistanceQueryImpl.java index d4272a34bf1..243f33e26dd 100644 --- a/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointDistanceQueryImpl.java +++ b/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointDistanceQueryImpl.java @@ -28,12 +28,24 @@ import org.apache.lucene.util.SloppyMath; 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; } } diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointPrefixTermsEnum.java b/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointPrefixTermsEnum.java index eeb58b2e348..f511392b2ee 100644 --- a/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointPrefixTermsEnum.java +++ b/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointPrefixTermsEnum.java @@ -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);