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.
|
* 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) {
|
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. */
|
/** 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]);
|
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 = polyLons;
|
||||||
this.x = toleranceConversion(polyLons);
|
this.y = polyLats;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override @SuppressWarnings("unchecked")
|
@Override @SuppressWarnings("unchecked")
|
||||||
|
@ -167,7 +159,8 @@ public final class GeoPointInPolygonQuery extends GeoPointInBBoxQueryImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean cellIntersectsShape(final double minLon, final double minLat, final double maxLon, final double maxLat) {
|
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
|
* 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!
|
* 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);
|
DETAIL_LEVEL = (short)(((GeoUtils.BITS<<1)-computeMaxShift())/2);
|
||||||
|
|
||||||
computeRange(0L, (short) (((GeoUtils.BITS) << 1) - 1));
|
computeRange(0L, (short) (((GeoUtils.BITS) << 1) - 1));
|
||||||
|
assert rangeBounds.isEmpty() == false;
|
||||||
Collections.sort(rangeBounds);
|
Collections.sort(rangeBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,31 +46,31 @@ public final class GeoUtils {
|
||||||
private 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));
|
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));
|
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));
|
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);
|
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);
|
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;
|
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;
|
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,
|
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) {
|
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));
|
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
|
* Computes whether or a 3dimensional line segment intersects or crosses a sphere
|
||||||
|
|
Loading…
Reference in New Issue