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/11/25 17:38:58 UTC

svn commit: r1716478 - in /lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src: java/org/apache/lucene/search/ java/org/apache/lucene/util/ test/org/apache/lucene/search/

Author: nknize
Date: Wed Nov 25 16:38:57 2015
New Revision: 1716478

URL: http://svn.apache.org/viewvc?rev=1716478&view=rev
Log:
LUCENE-6905: Unwrap center longitude for dateline crossing GeoPointDistanceQuery.

Modified:
    lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointDistanceQuery.java
    lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointDistanceQueryImpl.java
    lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/java/org/apache/lucene/util/GeoDistanceUtils.java
    lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/test/org/apache/lucene/search/TestGeoPointQuery.java

Modified: lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointDistanceQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointDistanceQuery.java?rev=1716478&r1=1716477&r2=1716478&view=diff
==============================================================================
--- lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointDistanceQuery.java (original)
+++ lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointDistanceQuery.java Wed Nov 25 16:38:57 2015
@@ -20,9 +20,9 @@ package org.apache.lucene.search;
 import java.io.IOException;
 
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.util.GeoDistanceUtils;
 import org.apache.lucene.util.GeoRect;
 import org.apache.lucene.util.GeoUtils;
-import org.apache.lucene.util.SloppyMath;
 
 /** Implements a simple point distance query on a GeoPoint field. This is based on
  * {@link org.apache.lucene.search.GeoPointInBBoxQuery} and is implemented using a two phase approach. First,
@@ -55,7 +55,7 @@ public class GeoPointDistanceQuery exten
     super(field, bbox.minLon, bbox.minLat, bbox.maxLon, bbox.maxLat);
     {
       // check longitudinal overlap (limits radius)
-      final double maxRadius = SloppyMath.haversin(centerLat, centerLon, centerLat, (180.0 + centerLon) % 360)*1000.0;
+      final double maxRadius = GeoDistanceUtils.maxRadialDistanceMeters(centerLon, centerLat);
       if (radiusMeters > maxRadius) {
         throw new IllegalArgumentException("radiusMeters " + radiusMeters + " exceeds maxRadius [" + maxRadius
             + "] at location [" + centerLon + " " + centerLat + "]");
@@ -84,18 +84,31 @@ public class GeoPointDistanceQuery exten
     if (getBoost() != 1f) {
       return super.rewrite(reader);
     }
+    // query crosses dateline; split into left and right queries
     if (maxLon < minLon) {
       BooleanQuery.Builder bqb = new BooleanQuery.Builder();
 
-      GeoPointDistanceQueryImpl left = new GeoPointDistanceQueryImpl(field, this, new GeoRect(GeoUtils.MIN_LON_INCL, maxLon,
-          minLat, maxLat));
+      // unwrap the longitude iff outside the specified min/max lon range
+      double unwrappedLon = centerLon;
+      if (unwrappedLon > maxLon) {
+        // unwrap left
+        unwrappedLon += -360.0D;
+      }
+      GeoPointDistanceQueryImpl left = new GeoPointDistanceQueryImpl(field, this, unwrappedLon,
+          new GeoRect(GeoUtils.MIN_LON_INCL, maxLon, minLat, maxLat));
       bqb.add(new BooleanClause(left, BooleanClause.Occur.SHOULD));
-      GeoPointDistanceQueryImpl right = new GeoPointDistanceQueryImpl(field, this, new GeoRect(minLon, GeoUtils.MAX_LON_INCL,
-          minLat, maxLat));
+
+      if (unwrappedLon < maxLon) {
+        // unwrap right
+        unwrappedLon += 360.0D;
+      }
+      GeoPointDistanceQueryImpl right = new GeoPointDistanceQueryImpl(field, this, unwrappedLon,
+          new GeoRect(minLon, GeoUtils.MAX_LON_INCL, minLat, maxLat));
       bqb.add(new BooleanClause(right, BooleanClause.Occur.SHOULD));
+
       return bqb.build();
     }
-    return new GeoPointDistanceQueryImpl(field, this, new GeoRect(this.minLon, this.maxLon, this.minLat, this.maxLat));
+    return new GeoPointDistanceQueryImpl(field, this, centerLon, new GeoRect(this.minLon, this.maxLon, this.minLat, this.maxLat));
   }
 
   @Override

Modified: lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointDistanceQueryImpl.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointDistanceQueryImpl.java?rev=1716478&r1=1716477&r2=1716478&view=diff
==============================================================================
--- lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointDistanceQueryImpl.java (original)
+++ lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/java/org/apache/lucene/search/GeoPointDistanceQueryImpl.java Wed Nov 25 16:38:57 2015
@@ -33,10 +33,13 @@ import org.apache.lucene.util.SloppyMath
  */
 final class GeoPointDistanceQueryImpl extends GeoPointInBBoxQueryImpl {
   private final GeoPointDistanceQuery query;
+  private final double centerLon;
 
-  GeoPointDistanceQueryImpl(final String field, final GeoPointDistanceQuery q, final GeoRect bbox) {
+  GeoPointDistanceQueryImpl(final String field, final GeoPointDistanceQuery q, final double centerLonUnwrapped,
+                            final GeoRect bbox) {
     super(field, bbox.minLon, bbox.minLat, bbox.maxLon, bbox.maxLat);
     query = q;
+    centerLon = centerLonUnwrapped;
   }
 
   @Override @SuppressWarnings("unchecked")
@@ -74,12 +77,12 @@ final class GeoPointDistanceQueryImpl ex
 
     @Override
     protected boolean cellCrosses(final double minLon, final double minLat, final double maxLon, final double maxLat) {
-      return GeoUtils.rectCrossesCircle(minLon, minLat, maxLon, maxLat, query.centerLon, query.centerLat, query.radiusMeters);
+      return GeoUtils.rectCrossesCircle(minLon, minLat, maxLon, maxLat, centerLon, query.centerLat, query.radiusMeters);
     }
 
     @Override
     protected boolean cellWithin(final double minLon, final double minLat, final double maxLon, final double maxLat) {
-      return GeoUtils.rectWithinCircle(minLon, minLat, maxLon, maxLat, query.centerLon, query.centerLat, query.radiusMeters);
+      return GeoUtils.rectWithinCircle(minLon, minLat, maxLon, maxLat, centerLon, query.centerLat, query.radiusMeters);
     }
 
     @Override
@@ -96,7 +99,7 @@ final class GeoPointDistanceQueryImpl ex
      */
     @Override
     protected boolean postFilter(final double lon, final double lat) {
-      return (SloppyMath.haversin(query.centerLat, query.centerLon, lat, lon) * 1000.0 <= query.radiusMeters);
+      return (SloppyMath.haversin(query.centerLat, centerLon, lat, lon) * 1000.0 <= query.radiusMeters);
     }
   }
 

Modified: lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/java/org/apache/lucene/util/GeoDistanceUtils.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/java/org/apache/lucene/util/GeoDistanceUtils.java?rev=1716478&r1=1716477&r2=1716478&view=diff
==============================================================================
--- lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/java/org/apache/lucene/util/GeoDistanceUtils.java (original)
+++ lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/java/org/apache/lucene/util/GeoDistanceUtils.java Wed Nov 25 16:38:57 2015
@@ -149,6 +149,14 @@ public class GeoDistanceUtils {
     }
   }
 
+  /** Returns the maximum distance/radius (in meters) from the point 'center' before overlapping */
+  public static double maxRadialDistanceMeters(final double centerLon, final double centerLat) {
+    if (Math.abs(centerLat) == GeoUtils.MAX_LAT_INCL) {
+      return SloppyMath.haversin(centerLat, centerLon, 0, centerLon)*1000.0;
+    }
+    return SloppyMath.haversin(centerLat, centerLon, centerLat, (GeoUtils.MAX_LON_INCL + centerLon) % 360)*1000.0;
+  }
+
   /**
    * Compute the inverse haversine to determine distance in degrees longitude for provided distance in meters
    * @param lat latitude to compute delta degrees lon

Modified: lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/test/org/apache/lucene/search/TestGeoPointQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/test/org/apache/lucene/search/TestGeoPointQuery.java?rev=1716478&r1=1716477&r2=1716478&view=diff
==============================================================================
--- lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/test/org/apache/lucene/search/TestGeoPointQuery.java (original)
+++ lucene/dev/branches/lucene_solr_5_4/lucene/sandbox/src/test/org/apache/lucene/search/TestGeoPointQuery.java Wed Nov 25 16:38:57 2015
@@ -95,7 +95,7 @@ public class TestGeoPointQuery extends B
         new GeoPointField(FIELD_NAME, -96.4538113027811, 32.94823588839368, storedPoint),
         new GeoPointField(FIELD_NAME, -96.65084838867188, 33.06047141970814, storedPoint),
         new GeoPointField(FIELD_NAME, -96.7772, 32.778650, storedPoint),
-        new GeoPointField(FIELD_NAME, -83.99724648980559, 58.29438379542874, storedPoint),
+        new GeoPointField(FIELD_NAME, -177.23537676036358, -88.56029371730983, storedPoint),
         new GeoPointField(FIELD_NAME, -26.779373834241003, 33.541429799076354, storedPoint),
         new GeoPointField(FIELD_NAME, -77.35379276106497, 26.774024500421728, storedPoint),
         new GeoPointField(FIELD_NAME, -14.796283808944777, -90.0, storedPoint),
@@ -289,6 +289,12 @@ public class TestGeoPointQuery extends B
     assertEquals("GeoDistanceQuery failed", 2, td.totalHits);
   }
 
+  /** see https://issues.apache.org/jira/browse/LUCENE-6905 */
+  public void testNonEmptyTermsEnum() throws Exception {
+    TopDocs td = geoDistanceQuery(-177.23537676036358, -88.56029371730983, 7757.999232959935, 20);
+    assertEquals("GeoDistanceQuery failed", 2, td.totalHits);
+  }
+
   public void testMultiValuedQuery() throws Exception {
     TopDocs td = bboxQuery(-96.4538113027811, 32.7559529921407, -96.7706036567688, 32.7756745755423, 20);
     // 3 single valued docs + 2 multi-valued docs
@@ -308,7 +314,7 @@ public class TestGeoPointQuery extends B
    */
   public void testGeoDistanceQueryHuge() throws Exception {
     TopDocs td = geoDistanceQuery(-96.4538113027811, 32.94823588839368, 6000000, 20);
-    assertEquals("GeoDistanceQuery failed",18, td.totalHits);
+    assertEquals("GeoDistanceQuery failed", 16, td.totalHits);
   }
 
   public void testGeoDistanceQueryCrossDateline() throws Exception {