mirror of https://github.com/apache/lucene.git
LUCENE-6859: GeoPointInPolygonQuery would occasionally fail with incorrect ranges
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1711014 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
60017e0ce3
commit
77f7614a46
|
@ -56,7 +56,7 @@ public final class GeoPointInPolygonQuery extends GeoPointInBBoxQueryImpl {
|
|||
* that fall within or on the boundary of the polygon defined by the input parameters.
|
||||
*/
|
||||
public GeoPointInPolygonQuery(final String field, final double[] polyLons, final double[] polyLats) {
|
||||
this(field, computeBBox(polyLons, polyLats), polyLons, polyLats);
|
||||
this(field, GeoUtils.polyToBBox(polyLons, polyLats), polyLons, polyLats);
|
||||
}
|
||||
|
||||
/** Common constructor, used only internally. */
|
||||
|
@ -75,16 +75,8 @@ public final class GeoPointInPolygonQuery extends GeoPointInBBoxQueryImpl {
|
|||
throw new IllegalArgumentException("first and last points of the polygon must be the same (it must close itself): polyLons[0]=" + polyLons[0] + " polyLons[" + (polyLons.length-1) + "]=" + polyLons[polyLons.length-1]);
|
||||
}
|
||||
|
||||
// convert polygon vertices to coordinates within tolerance
|
||||
this.x = toleranceConversion(polyLons);
|
||||
this.y = toleranceConversion(polyLats);
|
||||
}
|
||||
|
||||
private double[] toleranceConversion(double[] vals) {
|
||||
for (int i=0; i<vals.length; ++i) {
|
||||
vals[i] = ((int)(vals[i]/GeoUtils.TOLERANCE))*GeoUtils.TOLERANCE;
|
||||
}
|
||||
return vals;
|
||||
this.x = polyLons;
|
||||
this.y = polyLats;
|
||||
}
|
||||
|
||||
@Override @SuppressWarnings("unchecked")
|
||||
|
@ -167,7 +159,8 @@ public final class GeoPointInPolygonQuery extends GeoPointInBBoxQueryImpl {
|
|||
|
||||
@Override
|
||||
protected boolean cellIntersectsShape(final double minLon, final double minLat, final double maxLon, final double maxLat) {
|
||||
return cellWithin(minLon, minLat, maxLon, maxLat) || cellCrosses(minLon, minLat, maxLon, maxLat);
|
||||
return cellContains(minLon, minLat, maxLon, maxLat) || cellWithin(minLon, minLat, maxLon, maxLat)
|
||||
|| cellCrosses(minLon, minLat, maxLon, maxLat);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -183,32 +176,6 @@ public final class GeoPointInPolygonQuery extends GeoPointInBBoxQueryImpl {
|
|||
}
|
||||
}
|
||||
|
||||
private static GeoRect computeBBox(double[] polyLons, double[] polyLats) {
|
||||
if (polyLons.length != polyLats.length) {
|
||||
throw new IllegalArgumentException("polyLons and polyLats must be equal length");
|
||||
}
|
||||
|
||||
double minLon = Double.POSITIVE_INFINITY;
|
||||
double maxLon = Double.NEGATIVE_INFINITY;
|
||||
double minLat = Double.POSITIVE_INFINITY;
|
||||
double maxLat = Double.NEGATIVE_INFINITY;
|
||||
|
||||
for (int i=0;i<polyLats.length;i++) {
|
||||
if (GeoUtils.isValidLon(polyLons[i]) == false) {
|
||||
throw new IllegalArgumentException("invalid polyLons[" + i + "]=" + polyLons[i]);
|
||||
}
|
||||
if (GeoUtils.isValidLat(polyLats[i]) == false) {
|
||||
throw new IllegalArgumentException("invalid polyLats[" + i + "]=" + polyLats[i]);
|
||||
}
|
||||
minLon = Math.min(polyLons[i], minLon);
|
||||
maxLon = Math.max(polyLons[i], maxLon);
|
||||
minLat = Math.min(polyLats[i], minLat);
|
||||
maxLat = Math.max(polyLats[i], maxLat);
|
||||
}
|
||||
|
||||
return new GeoRect(minLon, maxLon, minLat, maxLat);
|
||||
}
|
||||
|
||||
/**
|
||||
* API utility method for returning the array of longitudinal values for this GeoPolygon
|
||||
* The returned array is not a copy so do not change it!
|
||||
|
|
|
@ -62,6 +62,7 @@ abstract class GeoPointTermsEnum extends FilteredTermsEnum {
|
|||
DETAIL_LEVEL = (short)(((GeoUtils.BITS<<1)-computeMaxShift())/2);
|
||||
|
||||
computeRange(0L, (short) (((GeoUtils.BITS) << 1) - 1));
|
||||
assert rangeBounds.isEmpty() == false;
|
||||
Collections.sort(rangeBounds);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,31 +46,31 @@ public final class GeoUtils {
|
|||
private GeoUtils() {
|
||||
}
|
||||
|
||||
public static Long mortonHash(final double lon, final double lat) {
|
||||
public static final Long mortonHash(final double lon, final double lat) {
|
||||
return BitUtil.interleave(scaleLon(lon), scaleLat(lat));
|
||||
}
|
||||
|
||||
public static double mortonUnhashLon(final long hash) {
|
||||
public static final double mortonUnhashLon(final long hash) {
|
||||
return unscaleLon(BitUtil.deinterleave(hash));
|
||||
}
|
||||
|
||||
public static double mortonUnhashLat(final long hash) {
|
||||
public static final double mortonUnhashLat(final long hash) {
|
||||
return unscaleLat(BitUtil.deinterleave(hash >>> 1));
|
||||
}
|
||||
|
||||
private static long scaleLon(final double val) {
|
||||
private static final long scaleLon(final double val) {
|
||||
return (long) ((val-MIN_LON_INCL) * LON_SCALE);
|
||||
}
|
||||
|
||||
private static long scaleLat(final double val) {
|
||||
private static final long scaleLat(final double val) {
|
||||
return (long) ((val-MIN_LAT_INCL) * LAT_SCALE);
|
||||
}
|
||||
|
||||
private static double unscaleLon(final long val) {
|
||||
private static final double unscaleLon(final long val) {
|
||||
return (val / LON_SCALE) + MIN_LON_INCL;
|
||||
}
|
||||
|
||||
private static double unscaleLat(final long val) {
|
||||
private static final double unscaleLat(final long val) {
|
||||
return (val / LAT_SCALE) + MIN_LAT_INCL;
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ public final class GeoUtils {
|
|||
*/
|
||||
public static boolean rectContains(final double aMinX, final double aMinY, final double aMaxX, final double aMaxY,
|
||||
final double bMinX, final double bMinY, final double bMaxX, final double bMaxY) {
|
||||
return !(bMinX < aMinX || bMinY < aMinY || bMaxX > aMaxX || bMaxY > aMaxY);
|
||||
return !(bMinX < aMinX || bMinY < aMinY || bMaxX > aMaxX || bMaxY > aMaxY);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -366,6 +366,33 @@ public final class GeoUtils {
|
|||
StrictMath.toDegrees(minLat), StrictMath.toDegrees(maxLat));
|
||||
}
|
||||
|
||||
public static GeoRect polyToBBox(double[] polyLons, double[] polyLats) {
|
||||
if (polyLons.length != polyLats.length) {
|
||||
throw new IllegalArgumentException("polyLons and polyLats must be equal length");
|
||||
}
|
||||
|
||||
double minLon = Double.POSITIVE_INFINITY;
|
||||
double maxLon = Double.NEGATIVE_INFINITY;
|
||||
double minLat = Double.POSITIVE_INFINITY;
|
||||
double maxLat = Double.NEGATIVE_INFINITY;
|
||||
|
||||
for (int i=0;i<polyLats.length;i++) {
|
||||
if (GeoUtils.isValidLon(polyLons[i]) == false) {
|
||||
throw new IllegalArgumentException("invalid polyLons[" + i + "]=" + polyLons[i]);
|
||||
}
|
||||
if (GeoUtils.isValidLat(polyLats[i]) == false) {
|
||||
throw new IllegalArgumentException("invalid polyLats[" + i + "]=" + polyLats[i]);
|
||||
}
|
||||
minLon = Math.min(polyLons[i], minLon);
|
||||
maxLon = Math.max(polyLons[i], maxLon);
|
||||
minLat = Math.min(polyLats[i], minLat);
|
||||
maxLat = Math.max(polyLats[i], maxLat);
|
||||
}
|
||||
|
||||
return new GeoRect(GeoUtils.unscaleLon(GeoUtils.scaleLon(minLon)), GeoUtils.unscaleLon(GeoUtils.scaleLon(maxLon)),
|
||||
GeoUtils.unscaleLat(GeoUtils.scaleLat(minLat)), GeoUtils.unscaleLat(GeoUtils.scaleLat(maxLat)));
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Computes whether or a 3dimensional line segment intersects or crosses a sphere
|
||||
|
|
Loading…
Reference in New Issue