You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by no...@apache.org on 2016/04/07 22:29:57 UTC
[25/50] [abbrv] lucene-solr:apiv2: LUCENE-7166: fix quantization bugs
in LatLonPoint and GeoPointField, remove test leniency
LUCENE-7166: fix quantization bugs in LatLonPoint and GeoPointField, remove test leniency
Squashed commit of the following:
commit 83c0f9b6158495b8b3d7108059a23bdf38e0f7f3
Author: Robert Muir <rm...@apache.org>
Date: Fri Apr 1 23:33:29 2016 -0400
fix geopoint
commit 97ebd2de516e61c236542fb2fb28e71cf6bdc403
Author: Robert Muir <rm...@apache.org>
Date: Fri Apr 1 23:06:05 2016 -0400
fix test and LatLonPoint encoding/quantization/box queries
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/f8ea8b85
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/f8ea8b85
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/f8ea8b85
Branch: refs/heads/apiv2
Commit: f8ea8b855e43fc0a2fa434ab8c366de810047c8f
Parents: 0166171
Author: Robert Muir <rm...@apache.org>
Authored: Sat Apr 2 07:16:55 2016 -0400
Committer: Robert Muir <rm...@apache.org>
Committed: Sat Apr 2 07:16:55 2016 -0400
----------------------------------------------------------------------
lucene/CHANGES.txt | 3 +
.../org/apache/lucene/document/LatLonPoint.java | 56 ++++++--
.../apache/lucene/document/TestLatLonPoint.java | 136 +++++++++++++++++--
.../geopoint/search/GeoPointMultiTermQuery.java | 12 +-
.../org/apache/lucene/spatial/util/GeoRect.java | 12 +-
.../spatial/util/BaseGeoPointTestCase.java | 33 ++++-
.../lucene/spatial/util/TestGeoUtils.java | 15 --
7 files changed, 212 insertions(+), 55 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f8ea8b85/lucene/CHANGES.txt
----------------------------------------------------------------------
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 8e95950..8dccacd 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -57,6 +57,9 @@ Bug Fixes
* LUCENE-7127: Fix corner case bugs in GeoPointDistanceQuery. (Robert Muir)
+* LUCENE-7166: Fix corner case bugs in LatLonPoint/GeoPointField bounding box
+ queries. (Robert Muir)
+
======================= Lucene 6.0.0 =======================
System Requirements
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f8ea8b85/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java
----------------------------------------------------------------------
diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java
index af014cb..507f543 100644
--- a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java
+++ b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java
@@ -97,10 +97,10 @@ public class LatLonPoint extends Field {
}
private static final int BITS = 32;
- private static final double LONGITUDE_ENCODE = (0x1L<<BITS)/360.0D;
- private static final double LONGITUDE_DECODE = 1/LONGITUDE_ENCODE;
- private static final double LATITUDE_ENCODE = (0x1L<<BITS)/180.0D;
- private static final double LATITUDE_DECODE = 1/LATITUDE_ENCODE;
+ private static final double LONGITUDE_MUL = (0x1L<<BITS)/360.0D;
+ private static final double LONGITUDE_DECODE = 1/LONGITUDE_MUL;
+ private static final double LATITUDE_MUL = (0x1L<<BITS)/180.0D;
+ private static final double LATITUDE_DECODE = 1/LATITUDE_MUL;
@Override
public String toString() {
@@ -132,7 +132,7 @@ public class LatLonPoint extends Field {
// public helper methods (e.g. for queries)
/**
- * Quantizes double (64 bit) latitude into 32 bits
+ * Quantizes double (64 bit) latitude into 32 bits (rounding down: in the direction of -90)
* @param latitude latitude value: must be within standard +/-90 coordinate bounds.
* @return encoded value as a 32-bit {@code int}
* @throws IllegalArgumentException if latitude is out of bounds
@@ -143,11 +143,26 @@ public class LatLonPoint extends Field {
if (latitude == 90.0D) {
latitude = Math.nextDown(latitude);
}
- return (int) Math.floor(latitude * LATITUDE_ENCODE);
+ return (int) Math.floor(latitude / LATITUDE_DECODE);
+ }
+
+ /**
+ * Quantizes double (64 bit) latitude into 32 bits (rounding up: in the direction of +90)
+ * @param latitude latitude value: must be within standard +/-90 coordinate bounds.
+ * @return encoded value as a 32-bit {@code int}
+ * @throws IllegalArgumentException if latitude is out of bounds
+ */
+ public static int encodeLatitudeCeil(double latitude) {
+ GeoUtils.checkLatitude(latitude);
+ // the maximum possible value cannot be encoded without overflow
+ if (latitude == 90.0D) {
+ latitude = Math.nextDown(latitude);
+ }
+ return (int) Math.ceil(latitude / LATITUDE_DECODE);
}
/**
- * Quantizes double (64 bit) longitude into 32 bits
+ * Quantizes double (64 bit) longitude into 32 bits (rounding down: in the direction of -180)
* @param longitude longitude value: must be within standard +/-180 coordinate bounds.
* @return encoded value as a 32-bit {@code int}
* @throws IllegalArgumentException if longitude is out of bounds
@@ -158,7 +173,22 @@ public class LatLonPoint extends Field {
if (longitude == 180.0D) {
longitude = Math.nextDown(longitude);
}
- return (int) Math.floor(longitude * LONGITUDE_ENCODE);
+ return (int) Math.floor(longitude / LONGITUDE_DECODE);
+ }
+
+ /**
+ * Quantizes double (64 bit) longitude into 32 bits (rounding up: in the direction of +180)
+ * @param longitude longitude value: must be within standard +/-180 coordinate bounds.
+ * @return encoded value as a 32-bit {@code int}
+ * @throws IllegalArgumentException if longitude is out of bounds
+ */
+ public static int encodeLongitudeCeil(double longitude) {
+ GeoUtils.checkLongitude(longitude);
+ // the maximum possible value cannot be encoded without overflow
+ if (longitude == 180.0D) {
+ longitude = Math.nextDown(longitude);
+ }
+ return (int) Math.ceil(longitude / LONGITUDE_DECODE);
}
/**
@@ -210,6 +240,14 @@ public class LatLonPoint extends Field {
NumericUtils.intToSortableBytes(encodeLongitude(longitude), bytes, Integer.BYTES);
return bytes;
}
+
+ /** sugar encodes a single point as a byte array, rounding values up */
+ private static byte[] encodeCeil(double latitude, double longitude) {
+ byte[] bytes = new byte[2 * Integer.BYTES];
+ NumericUtils.intToSortableBytes(encodeLatitudeCeil(latitude), bytes, 0);
+ NumericUtils.intToSortableBytes(encodeLongitudeCeil(longitude), bytes, Integer.BYTES);
+ return bytes;
+ }
/** helper: checks a fieldinfo and throws exception if its definitely not a LatLonPoint */
static void checkCompatible(FieldInfo fieldInfo) {
@@ -246,7 +284,7 @@ public class LatLonPoint extends Field {
* @throws IllegalArgumentException if {@code field} is null, or the box has invalid coordinates.
*/
public static Query newBoxQuery(String field, double minLatitude, double maxLatitude, double minLongitude, double maxLongitude) {
- byte[] lower = encode(minLatitude, minLongitude);
+ byte[] lower = encodeCeil(minLatitude, minLongitude);
byte[] upper = encode(maxLatitude, maxLongitude);
// Crosses date line: we just rewrite into OR of two bboxes, with longitude as an open range:
if (maxLongitude < minLongitude) {
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f8ea8b85/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPoint.java
----------------------------------------------------------------------
diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPoint.java b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPoint.java
index 045f8ba..73a3683 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPoint.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPoint.java
@@ -16,6 +16,7 @@
*/
package org.apache.lucene.document;
+import org.apache.lucene.spatial.util.GeoTestUtil;
import org.apache.lucene.util.LuceneTestCase;
/** Simple tests for {@link LatLonPoint} */
@@ -26,7 +27,7 @@ public class TestLatLonPoint extends LuceneTestCase {
assertEquals("LatLonPoint <field:18.313693958334625,-65.22744401358068>",(new LatLonPoint("field", 18.313694, -65.227444)).toString());
// looks crazy due to lossiness
- assertEquals("field:[17.99999997485429 TO 18.999999999068677],[-66.00000000558794 TO -65.00000006519258]", LatLonPoint.newBoxQuery("field", 18, 19, -66, -65).toString());
+ assertEquals("field:[18.000000016763806 TO 18.999999999068677],[-65.9999999217689 TO -65.00000006519258]", LatLonPoint.newBoxQuery("field", 18, 19, -66, -65).toString());
// distance query does not quantize inputs
assertEquals("field:18.0,19.0 +/- 25.0 meters", LatLonPoint.newDistanceQuery("field", 18, 19, 25).toString());
@@ -41,11 +42,11 @@ public class TestLatLonPoint extends LuceneTestCase {
int iters = atLeast(10000);
for(int iter=0;iter<iters;iter++) {
- double lat = -90 + 180.0 * random().nextDouble();
+ double lat = GeoTestUtil.nextLatitude();
double latEnc = LatLonPoint.decodeLatitude(LatLonPoint.encodeLatitude(lat));
assertEquals("lat=" + lat + " latEnc=" + latEnc + " diff=" + (lat - latEnc), lat, latEnc, ENCODING_TOLERANCE);
- double lon = -180 + 360.0 * random().nextDouble();
+ double lon = GeoTestUtil.nextLongitude();
double lonEnc = LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitude(lon));
assertEquals("lon=" + lon + " lonEnc=" + lonEnc + " diff=" + (lon - lonEnc), lon, lonEnc, ENCODING_TOLERANCE);
}
@@ -59,6 +60,31 @@ public class TestLatLonPoint extends LuceneTestCase {
assertEquals(180.0, LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitude(180.0)), ENCODING_TOLERANCE);
assertEquals(-180.0, LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitude(-180.0)), ENCODING_TOLERANCE);
}
+
+ public void testEncodeDecodeCeil() throws Exception {
+ // just for testing quantization error
+ final double ENCODING_TOLERANCE = 1e-7;
+
+ int iters = atLeast(10000);
+ for(int iter=0;iter<iters;iter++) {
+ double lat = GeoTestUtil.nextLatitude();
+ double latEnc = LatLonPoint.decodeLatitude(LatLonPoint.encodeLatitudeCeil(lat));
+ assertEquals("lat=" + lat + " latEnc=" + latEnc + " diff=" + (lat - latEnc), lat, latEnc, ENCODING_TOLERANCE);
+
+ double lon = GeoTestUtil.nextLongitude();
+ double lonEnc = LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitudeCeil(lon));
+ assertEquals("lon=" + lon + " lonEnc=" + lonEnc + " diff=" + (lon - lonEnc), lon, lonEnc, ENCODING_TOLERANCE);
+ }
+
+ // check edge/interesting cases explicitly
+ assertEquals(0.0, LatLonPoint.decodeLatitude(LatLonPoint.encodeLatitudeCeil(0.0)), ENCODING_TOLERANCE);
+ assertEquals(90.0, LatLonPoint.decodeLatitude(LatLonPoint.encodeLatitudeCeil(90.0)), ENCODING_TOLERANCE);
+ assertEquals(-90.0, LatLonPoint.decodeLatitude(LatLonPoint.encodeLatitudeCeil(-90.0)), ENCODING_TOLERANCE);
+
+ assertEquals(0.0, LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitudeCeil(0.0)), ENCODING_TOLERANCE);
+ assertEquals(180.0, LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitudeCeil(180.0)), ENCODING_TOLERANCE);
+ assertEquals(-180.0, LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitudeCeil(-180.0)), ENCODING_TOLERANCE);
+ }
public void testEncodeDecodeExtremeValues() throws Exception {
assertEquals(Integer.MIN_VALUE, LatLonPoint.encodeLatitude(-90.0));
@@ -69,12 +95,22 @@ public class TestLatLonPoint extends LuceneTestCase {
assertEquals(0, LatLonPoint.encodeLatitude(0.0));
assertEquals(Integer.MAX_VALUE, LatLonPoint.encodeLongitude(180.0));
}
+
+ public void testEncodeDecodeExtremeValuesCeil() throws Exception {
+ assertEquals(Integer.MIN_VALUE, LatLonPoint.encodeLatitudeCeil(-90.0));
+ assertEquals(0, LatLonPoint.encodeLatitudeCeil(0.0));
+ assertEquals(Integer.MAX_VALUE, LatLonPoint.encodeLatitudeCeil(90.0));
+
+ assertEquals(Integer.MIN_VALUE, LatLonPoint.encodeLongitudeCeil(-180.0));
+ assertEquals(0, LatLonPoint.encodeLatitudeCeil(0.0));
+ assertEquals(Integer.MAX_VALUE, LatLonPoint.encodeLongitudeCeil(180.0));
+ }
public void testEncodeDecodeIsStable() throws Exception {
int iters = atLeast(1000);
for(int iter=0;iter<iters;iter++) {
- double lat = -90 + 180.0 * random().nextDouble();
- double lon = -180 + 360.0 * random().nextDouble();
+ double lat = GeoTestUtil.nextLatitude();
+ double lon = GeoTestUtil.nextLongitude();
double latEnc = LatLonPoint.decodeLatitude(LatLonPoint.encodeLatitude(lat));
double lonEnc = LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitude(lon));
@@ -86,16 +122,92 @@ public class TestLatLonPoint extends LuceneTestCase {
}
}
+ public void testEncodeDecodeCeilIsStable() throws Exception {
+ int iters = atLeast(1000);
+ for(int iter=0;iter<iters;iter++) {
+ double lat = GeoTestUtil.nextLatitude();
+ double lon = GeoTestUtil.nextLongitude();
+
+ double latEnc = LatLonPoint.decodeLatitude(LatLonPoint.encodeLatitudeCeil(lat));
+ double lonEnc = LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitudeCeil(lon));
+
+ double latEnc2 = LatLonPoint.decodeLatitude(LatLonPoint.encodeLatitudeCeil(latEnc));
+ double lonEnc2 = LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitudeCeil(lonEnc));
+ assertEquals(latEnc, latEnc2, 0.0);
+ assertEquals(lonEnc, lonEnc2, 0.0);
+ }
+ }
+
/** make sure values always go down: this is important for edge case consistency */
public void testEncodeDecodeRoundsDown() throws Exception {
- int iters = atLeast(1000);
+ int iters = atLeast(10000);
for(int iter=0;iter<iters;iter++) {
- double lat = -90 + 180.0 * random().nextDouble();
- double lon = -180 + 360.0 * random().nextDouble();
- double latEnc = LatLonPoint.decodeLatitude(LatLonPoint.encodeLatitude(lat));
- double lonEnc = LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitude(lon));
- assertTrue(latEnc <= lat);
- assertTrue(lonEnc <= lon);
+ final double latBase = GeoTestUtil.nextLatitude();
+ final double lonBase = GeoTestUtil.nextLongitude();
+
+ // test above the value
+ double lat = latBase;
+ double lon = lonBase;
+ for (int i = 0; i < 1000; i++) {
+ lat = Math.min(90, Math.nextUp(lat));
+ lon = Math.min(180, Math.nextUp(lon));
+ double latEnc = LatLonPoint.decodeLatitude(LatLonPoint.encodeLatitude(lat));
+ double lonEnc = LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitude(lon));
+ assertTrue(latEnc <= lat);
+ assertTrue(lonEnc <= lon);
+ }
+
+ // test below the value
+ lat = latBase;
+ lon = lonBase;
+ for (int i = 0; i < 1000; i++) {
+ lat = Math.max(-90, Math.nextDown(lat));
+ lon = Math.max(-180, Math.nextDown(lon));
+ double latEnc = LatLonPoint.decodeLatitude(LatLonPoint.encodeLatitude(lat));
+ double lonEnc = LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitude(lon));
+ assertTrue(latEnc <= lat);
+ assertTrue(lonEnc <= lon);
+ }
+ }
+ }
+
+ /** bug in previous encoding! */
+ public void testSpecialBuggyValue() throws Exception {
+ double special = 124.40717171877621;
+ double lonEnc = LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitude(special));
+ assertTrue(lonEnc <= special);
+ }
+
+ /** make sure values can go up if we need */
+ public void testEncodeDecodeCeilRoundsUp() throws Exception {
+ int iters = atLeast(10000);
+ for(int iter=0;iter<iters;iter++) {
+ final double latBase = GeoTestUtil.nextLatitude();
+ final double lonBase = GeoTestUtil.nextLongitude();
+
+ // test above the value
+ double lat = latBase;
+ double lon = lonBase;
+ for (int i = 0; i < 1000; i++) {
+ lat = Math.min(90, Math.nextUp(lat));
+ lon = Math.min(180, Math.nextUp(lon));
+ double latEnc = LatLonPoint.decodeLatitude(LatLonPoint.encodeLatitudeCeil(lat));
+ double lonEnc = LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitudeCeil(lon));
+ assertTrue(latEnc >= lat);
+ assertTrue(lonEnc >= lon);
+ }
+
+ // test below the value
+ lat = latBase;
+ lon = lonBase;
+ for (int i = 0; i < 1000; i++) {
+ lat = Math.max(-90, Math.nextDown(lat));
+ lon = Math.max(-180, Math.nextDown(lon));
+ double latEnc = LatLonPoint.decodeLatitude(LatLonPoint.encodeLatitudeCeil(lat));
+ double lonEnc = LatLonPoint.decodeLongitude(LatLonPoint.encodeLongitudeCeil(lon));
+ assertTrue(latEnc >= lat);
+ assertTrue(lonEnc >= lon);
+ }
}
}
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f8ea8b85/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointMultiTermQuery.java
----------------------------------------------------------------------
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointMultiTermQuery.java b/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointMultiTermQuery.java
index f1f53e3..20026a1 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointMultiTermQuery.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointMultiTermQuery.java
@@ -27,7 +27,6 @@ import org.apache.lucene.search.Query;
import org.apache.lucene.util.AttributeSource;
import org.apache.lucene.spatial.geopoint.document.GeoPointField;
import org.apache.lucene.spatial.geopoint.document.GeoPointField.TermEncoding;
-import org.apache.lucene.spatial.util.GeoEncodingUtils;
import org.apache.lucene.spatial.util.GeoRelationUtils;
import org.apache.lucene.geo.GeoUtils;
import org.apache.lucene.util.SloppyMath;
@@ -44,6 +43,7 @@ abstract class GeoPointMultiTermQuery extends MultiTermQuery {
protected final double minLat;
protected final double maxLon;
protected final double maxLat;
+
protected final short maxShift;
protected final TermEncoding termEncoding;
protected final CellComparator cellComparator;
@@ -60,12 +60,10 @@ abstract class GeoPointMultiTermQuery extends MultiTermQuery {
GeoUtils.checkLongitude(minLon);
GeoUtils.checkLongitude(maxLon);
- final long minHash = GeoEncodingUtils.mortonHash(minLat, minLon);
- final long maxHash = GeoEncodingUtils.mortonHash(maxLat, maxLon);
- this.minLat = GeoEncodingUtils.mortonUnhashLat(minHash);
- this.maxLat = GeoEncodingUtils.mortonUnhashLat(maxHash);
- this.minLon = GeoEncodingUtils.mortonUnhashLon(minHash);
- this.maxLon = GeoEncodingUtils.mortonUnhashLon(maxHash);
+ this.minLat = minLat;
+ this.maxLat = maxLat;
+ this.minLon = minLon;
+ this.maxLon = maxLon;
this.maxShift = computeMaxShift();
this.termEncoding = termEncoding;
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f8ea8b85/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRect.java
----------------------------------------------------------------------
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRect.java b/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRect.java
index 391f6d7..fdde3bf 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRect.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRect.java
@@ -68,17 +68,17 @@ public class GeoRect {
@Override
public String toString() {
StringBuilder b = new StringBuilder();
- b.append("GeoRect(lon=");
+ b.append("GeoRect(lat=");
+ b.append(minLat);
+ b.append(" TO ");
+ b.append(maxLat);
+ b.append(" lon=");
b.append(minLon);
b.append(" TO ");
b.append(maxLon);
if (maxLon < minLon) {
- b.append(" (crosses dateline!)");
+ b.append(" [crosses dateline!]");
}
- b.append(" lat=");
- b.append(minLat);
- b.append(" TO ");
- b.append(maxLat);
b.append(")");
return b.toString();
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f8ea8b85/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java
----------------------------------------------------------------------
diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java b/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java
index 93b0b1c..182ec6f 100644
--- a/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java
+++ b/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java
@@ -538,8 +538,6 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
int iters = atLeast(25);
for (int iter=0;iter<iters;iter++) {
GeoRect rect = randomRect(small);
- // TODO: why does this test need this quantization leniency? something is not right
- rect = new GeoRect(quantizeLat(rect.minLat), quantizeLat(rect.maxLat), quantizeLon(rect.minLon), quantizeLon(rect.maxLon));
if (VERBOSE) {
System.out.println("\nTEST: iter=" + iter + " rect=" + rect);
@@ -823,8 +821,6 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
}
GeoRect rect = randomRect(small);
- // TODO: why does this test need this quantization leniency? something is not right
- rect = new GeoRect(quantizeLat(rect.minLat), quantizeLat(rect.maxLat), quantizeLon(rect.minLon), quantizeLon(rect.maxLon));
Query query = newRectQuery(FIELD_NAME, rect.minLat, rect.maxLat, rect.minLon, rect.maxLon);
@@ -1185,6 +1181,8 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
break;
}
}
+ // this test works in quantized space: for testing inclusiveness of exact edges it must be aware of index-time quantization!
+ rect = new GeoRect(quantizeLat(rect.minLat), quantizeLat(rect.maxLat), quantizeLon(rect.minLon), quantizeLon(rect.maxLon));
Directory dir = newDirectory();
IndexWriterConfig iwc = newIndexWriterConfig();
// Else seeds may not reproduce:
@@ -1219,7 +1217,29 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
}
IndexReader r = w.getReader();
IndexSearcher s = newSearcher(r, false);
+ // exact edge cases
assertEquals(8, s.count(newRectQuery(FIELD_NAME, rect.minLat, rect.maxLat, rect.minLon, rect.maxLon)));
+
+ // expand 1 ulp in each direction
+ assumeFalse("can't expand box, its too big already", rect.minLat == -90);
+ assumeFalse("can't expand box, its too big already", rect.maxLat == 90);
+ assumeFalse("can't expand box, its too big already", rect.minLon == -180);
+ assumeFalse("can't expand box, its too big already", rect.maxLon == 180);
+ assertEquals(8, s.count(newRectQuery(FIELD_NAME, Math.nextDown(rect.minLat), rect.maxLat, rect.minLon, rect.maxLon)));
+ assertEquals(8, s.count(newRectQuery(FIELD_NAME, rect.minLat, Math.nextUp(rect.maxLat), rect.minLon, rect.maxLon)));
+ assertEquals(8, s.count(newRectQuery(FIELD_NAME, rect.minLat, rect.maxLat, Math.nextDown(rect.minLon), rect.maxLon)));
+ assertEquals(8, s.count(newRectQuery(FIELD_NAME, rect.minLat, rect.maxLat, rect.minLon, Math.nextUp(rect.maxLon))));
+
+ // now shrink 1 ulp in each direction: it should not include bogus stuff
+ assumeFalse("can't shrink box, its too small already", rect.minLat == 90);
+ assumeFalse("can't shrink box, its too small already", rect.maxLat == -90);
+ assumeFalse("can't shrink box, its too small already", rect.minLon == 180);
+ assumeFalse("can't shrink box, its too small already", rect.maxLon == -180);
+ // note we put points on "sides" not just "corners" so we just shrink all 4 at once for now: it should exclude all points!
+ assertEquals(0, s.count(newRectQuery(FIELD_NAME, Math.nextUp(rect.minLat),
+ Math.nextDown(rect.maxLat),
+ Math.nextUp(rect.minLon),
+ Math.nextDown(rect.maxLon))));
r.close();
w.close();
dir.close();
@@ -1356,6 +1376,7 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
/** return topdocs over a small set of points in field "point" */
private TopDocs searchSmallSet(Query query, int size) throws Exception {
// this is a simple systematic test, indexing these points
+ // TODO: fragile: does not understand quantization in any way yet uses extremely high precision!
double[][] pts = new double[][] {
{ 32.763420, -96.774 },
{ 32.7559529921407, -96.7759895324707 },
@@ -1417,7 +1438,7 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
}
public void testSmallSetRect() throws Exception {
- TopDocs td = searchSmallSet(newRectQuery("point", 32.778650, 32.778950, -96.7772, -96.77690000), 5);
+ TopDocs td = searchSmallSet(newRectQuery("point", 32.778, 32.779, -96.778, -96.777), 5);
assertEquals(4, td.totalHits);
}
@@ -1427,7 +1448,7 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
}
public void testSmallSetMultiValued() throws Exception {
- TopDocs td = searchSmallSet(newRectQuery("point", 32.7559529921407, 32.7756745755423, -96.4538113027811, -96.7706036567688), 20);
+ TopDocs td = searchSmallSet(newRectQuery("point", 32.755, 32.776, -96.454, -96.770), 20);
// 3 single valued docs + 2 multi-valued docs
assertEquals(5, td.totalHits);
}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f8ea8b85/lucene/spatial/src/test/org/apache/lucene/spatial/util/TestGeoUtils.java
----------------------------------------------------------------------
diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/util/TestGeoUtils.java b/lucene/spatial/src/test/org/apache/lucene/spatial/util/TestGeoUtils.java
index 06ef48c..28b885a 100644
--- a/lucene/spatial/src/test/org/apache/lucene/spatial/util/TestGeoUtils.java
+++ b/lucene/spatial/src/test/org/apache/lucene/spatial/util/TestGeoUtils.java
@@ -101,21 +101,6 @@ public class TestGeoUtils extends LuceneTestCase {
}
}
- /** make sure values always go down: this is important for edge case consistency */
- public void testEncodeDecodeRoundsDown() throws Exception {
- int iters = atLeast(1000);
- for(int iter=0;iter<iters;iter++) {
- double lat = -90 + 180.0 * random().nextDouble();
- double lon = -180 + 360.0 * random().nextDouble();
-
- long enc = GeoEncodingUtils.mortonHash(lat, lon);
- double latEnc = GeoEncodingUtils.mortonUnhashLat(enc);
- double lonEnc = GeoEncodingUtils.mortonUnhashLon(enc);
- assertTrue(latEnc <= lat);
- assertTrue(lonEnc <= lon);
- }
- }
-
public void testScaleUnscaleIsStable() throws Exception {
int iters = atLeast(1000);
boolean small = random().nextBoolean();