You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by nk...@apache.org on 2015/10/28 14:54:37 UTC

svn commit: r1711014 - in /lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene: search/GeoPointInPolygonQuery.java search/GeoPointTermsEnum.java util/GeoUtils.java

Author: nknize
Date: Wed Oct 28 13:54:36 2015
New Revision: 1711014

URL: http://svn.apache.org/viewvc?rev=1711014&view=rev
Log:
LUCENE-6859: GeoPointInPolygonQuery would occasionally fail with incorrect ranges

Modified:
    lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointInPolygonQuery.java
    lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointTermsEnum.java
    lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/util/GeoUtils.java

Modified: lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointInPolygonQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointInPolygonQuery.java?rev=1711014&r1=1711013&r2=1711014&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointInPolygonQuery.java (original)
+++ lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointInPolygonQuery.java Wed Oct 28 13:54:36 2015
@@ -56,7 +56,7 @@ public final class GeoPointInPolygonQuer
    * 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 GeoPointInPolygonQuer
       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 GeoPointInPolygonQuer
 
     @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 GeoPointInPolygonQuer
     }
   }
 
-  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!

Modified: lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointTermsEnum.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointTermsEnum.java?rev=1711014&r1=1711013&r2=1711014&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointTermsEnum.java (original)
+++ lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointTermsEnum.java Wed Oct 28 13:54:36 2015
@@ -62,6 +62,7 @@ abstract class GeoPointTermsEnum extends
     DETAIL_LEVEL = (short)(((GeoUtils.BITS<<1)-computeMaxShift())/2);
 
     computeRange(0L, (short) (((GeoUtils.BITS) << 1) - 1));
+    assert rangeBounds.isEmpty() == false;
     Collections.sort(rangeBounds);
   }
 

Modified: lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/util/GeoUtils.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/util/GeoUtils.java?rev=1711014&r1=1711013&r2=1711014&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/util/GeoUtils.java (original)
+++ lucene/dev/trunk/lucene/sandbox/src/java/org/apache/lucene/util/GeoUtils.java Wed Oct 28 13:54:36 2015
@@ -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