You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mi...@apache.org on 2015/05/27 16:14:51 UTC

svn commit: r1682036 - in /lucene/dev/branches/LUCENE-6481/lucene/sandbox/src: java/org/apache/lucene/search/GeoBoundingBox.java java/org/apache/lucene/search/GeoPointInPolygonQuery.java test/org/apache/lucene/search/TestGeoPointQuery.java

Author: mikemccand
Date: Wed May 27 14:14:51 2015
New Revision: 1682036

URL: http://svn.apache.org/r1682036
Log:
LUCENE-6481: restrict random test cases to 'smallish' bbox; switch static factory for polygon query to ctor

Added:
    lucene/dev/branches/LUCENE-6481/lucene/sandbox/src/java/org/apache/lucene/search/GeoBoundingBox.java   (with props)
Modified:
    lucene/dev/branches/LUCENE-6481/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointInPolygonQuery.java
    lucene/dev/branches/LUCENE-6481/lucene/sandbox/src/test/org/apache/lucene/search/TestGeoPointQuery.java

Added: lucene/dev/branches/LUCENE-6481/lucene/sandbox/src/java/org/apache/lucene/search/GeoBoundingBox.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-6481/lucene/sandbox/src/java/org/apache/lucene/search/GeoBoundingBox.java?rev=1682036&view=auto
==============================================================================
--- lucene/dev/branches/LUCENE-6481/lucene/sandbox/src/java/org/apache/lucene/search/GeoBoundingBox.java (added)
+++ lucene/dev/branches/LUCENE-6481/lucene/sandbox/src/java/org/apache/lucene/search/GeoBoundingBox.java Wed May 27 14:14:51 2015
@@ -0,0 +1,47 @@
+package org.apache.lucene.search;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.util.GeoUtils;
+
+/** NOTE: package private; just used so {@link GeoPointInBBoxQuery} can communicate its bounding box to {@link GeoPointInBBoxQuery}. */
+class GeoBoundingBox {
+  public final double minLon;
+  public final double maxLon;
+  public final double minLat;
+  public final double maxLat;
+
+  public GeoBoundingBox(double minLon, double maxLon, double minLat, double maxLat) {
+    if (GeoUtils.isValidLon(minLon) == false) {
+      throw new IllegalArgumentException("invalid minLon " + minLon);
+    }
+    if (GeoUtils.isValidLon(maxLon) == false) {
+      throw new IllegalArgumentException("invalid maxLon " + minLon);
+    }
+    if (GeoUtils.isValidLat(minLat) == false) {
+      throw new IllegalArgumentException("invalid minLat " + minLat);
+    }
+    if (GeoUtils.isValidLat(maxLat) == false) {
+      throw new IllegalArgumentException("invalid maxLat " + minLat);
+    }
+    this.minLon = minLon;
+    this.maxLon = maxLon;
+    this.minLat = minLat;
+    this.maxLat = maxLat;
+  }
+}

Modified: lucene/dev/branches/LUCENE-6481/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointInPolygonQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-6481/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointInPolygonQuery.java?rev=1682036&r1=1682035&r2=1682036&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-6481/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointInPolygonQuery.java (original)
+++ lucene/dev/branches/LUCENE-6481/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointInPolygonQuery.java Wed May 27 14:14:51 2015
@@ -55,8 +55,16 @@ public final class GeoPointInPolygonQuer
 
   /**
    * Constructs a new GeoPolygonQuery that will match encoded {@link org.apache.lucene.document.GeoPointField} terms
-   * that fall within or on the boundary of the polygon defined by the input parameters. This constructor requires a
-   * precomputed bounding box. As an alternative the {@link GeoPointInPolygonQuery#newPolygonQuery} static factory can
+   * 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);
+  }
+
+  /**
+   * Expert: constructs a new GeoPolygonQuery that will match encoded {@link org.apache.lucene.document.GeoPointField} terms
+   * that fall within or on the boundary of the polygon defined by the input parameters.  This constructor requires a
+   * precomputed bounding box. As an alternative, {@link GeoPointInPolygonQuery(String,double[],double[])} can
    * be used to compute the bounding box during construction
    *
    * @param field the field name
@@ -69,7 +77,14 @@ public final class GeoPointInPolygonQuer
    */
   public GeoPointInPolygonQuery(final String field, final double minLon, final double minLat, final double maxLon,
                                 final double maxLat, final double[] polyLons, final double[] polyLats) {
-    super(field, minLon, minLat, maxLon, maxLat);
+    // TODO: should we remove this?  It's dangerous .. app could accidentally provide too-small bbox?
+    // we should at least verify that bbox does in fact fully contain the poly?
+    this(field, new GeoBoundingBox(minLon, maxLon, minLat, maxLat), polyLons, polyLats);
+  }
+
+  /** Common constructor, used only internally. */
+  private GeoPointInPolygonQuery(final String field, GeoBoundingBox bbox, final double[] polyLons, final double[] polyLats) {
+    super(field, bbox.minLon, bbox.minLat, bbox.maxLon, bbox.maxLat);
     if (polyLats.length != polyLons.length) {
       throw new IllegalArgumentException("polyLats and polyLons must be equal length");
     }
@@ -83,39 +98,10 @@ 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]);
     }
 
-    // nocommit we should at least assert that bbox does in fact fully contain the poly?
-    for(int i=0;i<polyLons.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]);
-      }
-    }
     this.x = polyLons;
     this.y = polyLats;
   }
 
-  /**
-   * Static method call to construct a
-   * {@link #GeoPointInPolygonQuery(String, double, double, double, double, double[], double[])
-   * GeoPolygonQuery(field, minLon, minLat, maxLon, maxLat, polyLons, polyLats)} by first computing the bounding
-   * box lat/lon ranges
-   */
-  // TODO: change this to normal ctor ... silly java requiring super() first
-  public static GeoPointInPolygonQuery newPolygonQuery(final String field, final double[] polyLons, final double[] polyLats) {
-    assert polyLons.length == polyLats.length;
-    double minLon, maxLon, minLat, maxLat;
-    int i=1;
-    for(minLon=maxLon=polyLons[0], minLat=maxLat=polyLats[0]; i<polyLons.length; ++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 GeoPointInPolygonQuery(field, minLon, minLat, maxLon, maxLat, polyLons, polyLats);
-  }
-
   @Override @SuppressWarnings("unchecked")
   protected TermsEnum getTermsEnum(final Terms terms, AttributeSource atts) throws IOException {
     final Long min = GeoUtils.mortonHash(minLon, minLat);
@@ -213,4 +199,30 @@ public final class GeoPointInPolygonQuer
       return AcceptStatus.YES;
     }
   }
+
+  private static GeoBoundingBox 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 GeoBoundingBox(minLon, maxLon, minLat, maxLat);
+  }
 }

Modified: lucene/dev/branches/LUCENE-6481/lucene/sandbox/src/test/org/apache/lucene/search/TestGeoPointQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-6481/lucene/sandbox/src/test/org/apache/lucene/search/TestGeoPointQuery.java?rev=1682036&r1=1682035&r2=1682036&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-6481/lucene/sandbox/src/test/org/apache/lucene/search/TestGeoPointQuery.java (original)
+++ lucene/dev/branches/LUCENE-6481/lucene/sandbox/src/test/org/apache/lucene/search/TestGeoPointQuery.java Wed May 27 14:14:51 2015
@@ -61,14 +61,20 @@ public class TestGeoPointQuery extends L
 
   private static final String FIELD_NAME = "geoField";
 
-  private static boolean smallBBox;
+  // Global bounding box we will "cover" in the random test; we have to make this "smallish" else the queries take very long:
+  private static double originLat;
+  private static double originLon;
+  private static double range;
 
   @BeforeClass
   public static void beforeClass() throws Exception {
     directory = newDirectory();
-    smallBBox = random().nextBoolean();
+    // Between 1.0 and 3.0:
+    range = 2*(random().nextDouble() + 0.5);
+    originLon = GeoUtils.MIN_LON_INCL + range + (GeoUtils.MAX_LON_INCL - GeoUtils.MIN_LON_INCL - 2*range) * random().nextDouble();
+    originLat = GeoUtils.MIN_LAT_INCL + range + (GeoUtils.MAX_LAT_INCL - GeoUtils.MIN_LAT_INCL - 2*range) * random().nextDouble();
     if (VERBOSE) {
-      System.out.println("TEST: smallBBox=" + smallBBox);
+      System.out.println("TEST: originLon=" + originLon + " originLat=" + originLat + " range=" + range);
     }
     RandomIndexWriter writer = new RandomIndexWriter(random(), directory,
             newIndexWriterConfig(new MockAnalyzer(random()))
@@ -112,7 +118,7 @@ public class TestGeoPointQuery extends L
   }
 
   private TopDocs polygonQuery(double[] lon, double[] lat, int limit) throws Exception {
-    GeoPointInPolygonQuery q = GeoPointInPolygonQuery.newPolygonQuery(FIELD_NAME, lon, lat);
+    GeoPointInPolygonQuery q = new GeoPointInPolygonQuery(FIELD_NAME, lon, lat);
     return searcher.search(q, limit);
   }
 
@@ -401,18 +407,10 @@ public class TestGeoPointQuery extends L
   }
 
   private static double randomLat() {
-    if (smallBBox) {
-      return 2.0 * (random().nextDouble()-0.5);
-    } else {
-      return -90 + 180.0 * random().nextDouble();
-    }
+    return originLat + range * (random().nextDouble()-0.5);
   }
 
   private static double randomLon() {
-    if (smallBBox) {
-      return 2.0 * (random().nextDouble()-0.5);
-    } else {
-      return -180 + 360.0 * random().nextDouble();
-    }
+    return originLon + range * (random().nextDouble()-0.5);
   }
 }