You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by rm...@apache.org on 2016/03/28 17:46:31 UTC
lucene-solr:master: factor out polygon/box generation into
GeoTestUtil. removes lots of leniency and unnecessary quantization! may cause
failures!!!!
Repository: lucene-solr
Updated Branches:
refs/heads/master 010f02216 -> 956e4363f
factor out polygon/box generation into GeoTestUtil. removes lots of leniency and unnecessary quantization! may cause failures!!!!
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/956e4363
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/956e4363
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/956e4363
Branch: refs/heads/master
Commit: 956e4363f10718096c3c522fb3798c8b389ab953
Parents: 010f022
Author: Robert Muir <rm...@apache.org>
Authored: Mon Mar 28 11:48:14 2016 -0400
Committer: Robert Muir <rm...@apache.org>
Committed: Mon Mar 28 11:48:14 2016 -0400
----------------------------------------------------------------------
.../spatial/util/BaseGeoPointTestCase.java | 165 +++---------------
.../apache/lucene/spatial/util/GeoTestUtil.java | 167 ++++++++++++++++++-
2 files changed, 192 insertions(+), 140 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/956e4363/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 c0633eb..e25266a 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
@@ -19,13 +19,11 @@ package org.apache.lucene.spatial.util;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.lucene.analysis.MockAnalyzer;
import org.apache.lucene.codecs.FilterCodec;
@@ -438,7 +436,7 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
int iters = atLeast(25);
for (int iter=0;iter<iters;iter++) {
- GeoRect rect = randomRect(small, small == false);
+ GeoRect rect = randomRect(small);
if (VERBOSE) {
System.out.println("\nTEST: iter=" + iter + " rect=" + rect);
@@ -609,67 +607,7 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
return quantizeLon(result);
}
- /** Returns {polyLats, polyLons} double[] array */
- private double[][] surpriseMePolygon() {
- // repeat until we get a poly that doesn't cross dateline:
- newPoly:
- while (true) {
- //System.out.println("\nPOLY ITER");
- double centerLat = randomLat(false);
- double centerLon = randomLon(false);
-
- double radius = 0.1 + 20 * random().nextDouble();
- double radiusDelta = random().nextDouble();
-
- ArrayList<Double> lats = new ArrayList<>();
- ArrayList<Double> lons = new ArrayList<>();
- double angle = 0.0;
- while (true) {
- angle += random().nextDouble()*40.0;
- //System.out.println(" angle " + angle);
- if (angle > 360) {
- break;
- }
- double len = radius * (1.0 - radiusDelta + radiusDelta * random().nextDouble());
- //System.out.println(" len=" + len);
- double lat = centerLat + len * Math.cos(Math.toRadians(angle));
- double lon = centerLon + len * Math.sin(Math.toRadians(angle));
- if (lon <= GeoUtils.MIN_LON_INCL || lon >= GeoUtils.MAX_LON_INCL) {
- // cannot cross dateline: try again!
- continue newPoly;
- }
- if (lat > 90) {
- // cross the north pole
- lat = 180 - lat;
- lon = 180 - lon;
- } else if (lat < -90) {
- // cross the south pole
- lat = -180 - lat;
- lon = 180 - lon;
- }
- if (lon <= GeoUtils.MIN_LON_INCL || lon >= GeoUtils.MAX_LON_INCL) {
- // cannot cross dateline: try again!
- continue newPoly;
- }
- lats.add(lat);
- lons.add(lon);
-
- //System.out.println(" lat=" + lats.get(lats.size()-1) + " lon=" + lons.get(lons.size()-1));
- }
-
- // close it
- lats.add(lats.get(0));
- lons.add(lons.get(0));
- double[] latsArray = new double[lats.size()];
- double[] lonsArray = new double[lons.size()];
- for(int i=0;i<lats.size();i++) {
- latsArray[i] = lats.get(i);
- lonsArray[i] = lons.get(i);
- }
- return new double[][] {latsArray, lonsArray};
- }
- }
/** Override this to quantize randomly generated lat, so the test won't fail due to quantization errors, which are 1) annoying to debug,
* and 2) should never affect "real" usage terribly. */
@@ -683,25 +621,12 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
return lon;
}
- protected GeoRect randomRect(boolean small, boolean canCrossDateLine) {
- double lat0 = randomLat(small);
- double lat1 = randomLat(small);
- double lon0 = randomLon(small);
- double lon1 = randomLon(small);
-
- if (lat1 < lat0) {
- double x = lat0;
- lat0 = lat1;
- lat1 = x;
- }
-
- if (canCrossDateLine == false && lon1 < lon0) {
- double x = lon0;
- lon0 = lon1;
- lon1 = x;
+ protected GeoRect randomRect(boolean small) {
+ if (small) {
+ return GeoTestUtil.nextBoxNear(originLat, originLon);
+ } else {
+ return GeoTestUtil.nextBox();
}
-
- return new GeoRect(lat0, lat1, lon0, lon1);
}
protected void initIndexWriterConfig(String field, IndexWriterConfig iwc) {
@@ -726,17 +651,6 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
|| GeoRelationUtils.pointInRectPrecise(pointLat, pointLon, rect.minLat, rect.maxLat, rect.minLon, 180.0);
}
}
-
- static final boolean polygonContainsPoint(double polyLats[], double polyLons[], double pointLat, double pointLon) {
- return GeoRelationUtils.pointInPolygon(polyLats, polyLons, pointLat, pointLon);
- }
-
- static final boolean circleContainsPoint(double centerLat, double centerLon, double radiusMeters, double pointLat, double pointLon) {
- double distanceMeters = SloppyMath.haversinMeters(centerLat, centerLon, pointLat, pointLon);
- boolean result = distanceMeters <= radiusMeters;
- //System.out.println(" shouldMatch? centerLon=" + centerLon + " centerLat=" + centerLat + " pointLon=" + pointLon + " pointLat=" + pointLat + " result=" + result + " distanceMeters=" + (distanceKM * 1000));
- return result;
- }
private void verify(boolean small, double[] lats, double[] lons) throws Exception {
verifyRandomRectangles(small, lats, lons);
@@ -800,8 +714,7 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
System.out.println("\nTEST: iter=" + iter + " s=" + s);
}
- // Rect: don't allow dateline crossing when testing small:
- GeoRect rect = randomRect(small, small == false);
+ GeoRect rect = randomRect(small);
Query query = newRectQuery(FIELD_NAME, rect.minLat, rect.maxLat, rect.minLon, rect.maxLon);
@@ -981,7 +894,7 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
} else if (Double.isNaN(lats[id])) {
expected = false;
} else {
- expected = circleContainsPoint(centerLat, centerLon, radiusMeters, lats[id], lons[id]);
+ expected = SloppyMath.haversinMeters(centerLat, centerLon, lats[id], lons[id]) <= radiusMeters;
}
if (hits.get(docID) != expected) {
@@ -1073,49 +986,16 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
System.out.println("\nTEST: iter=" + iter + " s=" + s);
}
- // TODO: poly query can't handle dateline crossing yet:
- final GeoRect bbox = randomRect(small, false);
-
// Polygon
- final double[] polyLats;
- final double[] polyLons;
- // TODO: factor this out, maybe if we add Polygon class?
- switch (random().nextInt(3)) {
- case 0:
- // box
- polyLats = new double[5];
- polyLons = new double[5];
- polyLats[0] = bbox.minLat;
- polyLons[0] = bbox.minLon;
- polyLats[1] = bbox.maxLat;
- polyLons[1] = bbox.minLon;
- polyLats[2] = bbox.maxLat;
- polyLons[2] = bbox.maxLon;
- polyLats[3] = bbox.minLat;
- polyLons[3] = bbox.maxLon;
- polyLats[4] = bbox.minLat;
- polyLons[4] = bbox.minLon;
- break;
- case 1:
- // right triangle
- polyLats = new double[4];
- polyLons = new double[4];
- polyLats[0] = bbox.minLat;
- polyLons[0] = bbox.minLon;
- polyLats[1] = bbox.maxLat;
- polyLons[1] = bbox.minLon;
- polyLats[2] = bbox.maxLat;
- polyLons[2] = bbox.maxLon;
- polyLats[3] = bbox.minLat;
- polyLons[3] = bbox.minLon;
- break;
- default:
- // surprise me!
- double[][] res = surpriseMePolygon();
- polyLats = res[0];
- polyLons = res[1];
- break;
+ final double[][] polygon;
+ if (small) {
+ polygon = GeoTestUtil.nextPolygonNear(originLat, originLon);
+ } else {
+ polygon = GeoTestUtil.nextPolygon();
}
+
+ final double[] polyLats = polygon[0];
+ final double[] polyLons = polygon[1];
Query query = newPolygonQuery(FIELD_NAME, polyLats, polyLons);
if (VERBOSE) {
@@ -1153,7 +1033,7 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
} else if (Double.isNaN(lats[id])) {
expected = false;
} else {
- expected = polygonContainsPoint(polyLats, polyLons, lats[id], lons[id]);
+ expected = GeoRelationUtils.pointInPolygon(polyLats, polyLons, lats[id], lons[id]);
}
if (hits.get(docID) != expected) {
@@ -1186,7 +1066,14 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
}
public void testRectBoundariesAreInclusive() throws Exception {
- GeoRect rect = randomRect(random().nextBoolean(), false);
+ GeoRect rect;
+ // TODO: why this dateline leniency???
+ while (true) {
+ rect = randomRect(random().nextBoolean());
+ if (rect.crossesDateline() == false) {
+ break;
+ }
+ }
Directory dir = newDirectory();
IndexWriterConfig iwc = newIndexWriterConfig();
RandomIndexWriter w = new RandomIndexWriter(random(), dir, iwc);
@@ -1319,7 +1206,7 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase {
public void testEquals() throws Exception {
Query q1, q2;
- GeoRect rect = randomRect(false, true);
+ GeoRect rect = randomRect(false);
q1 = newRectQuery("field", rect.minLat, rect.maxLat, rect.minLon, rect.maxLon);
q2 = newRectQuery("field", rect.minLat, rect.maxLat, rect.minLon, rect.maxLon);
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/956e4363/lucene/spatial/src/test/org/apache/lucene/spatial/util/GeoTestUtil.java
----------------------------------------------------------------------
diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/util/GeoTestUtil.java b/lucene/spatial/src/test/org/apache/lucene/spatial/util/GeoTestUtil.java
index f28e623..0059888 100644
--- a/lucene/spatial/src/test/org/apache/lucene/spatial/util/GeoTestUtil.java
+++ b/lucene/spatial/src/test/org/apache/lucene/spatial/util/GeoTestUtil.java
@@ -16,6 +16,7 @@
*/
package org.apache.lucene.spatial.util;
+import java.util.ArrayList;
import java.util.Random;
import com.carrotsearch.randomizedtesting.RandomizedContext;
@@ -27,7 +28,6 @@ public class GeoTestUtil {
public static double nextLatitude() {
return -90 + 180.0 * random().nextDouble();
}
-
/** returns next pseudorandom longitude (anywhere) */
public static double nextLongitude() {
@@ -68,6 +68,171 @@ public class GeoTestUtil {
return normalizeLongitude(randomRangeMaybeSlightlyOutside(minLongitude, maxLongitude));
}
+ /** returns next pseudorandom box: can cross the 180th meridian */
+ public static GeoRect nextBox() {
+ return nextBoxInternal(nextLatitude(), nextLatitude(), nextLongitude(), nextLongitude(), true);
+ }
+
+ /** returns next pseudorandom box, can cross the 180th meridian, kinda close to {@code otherLatitude} and {@code otherLongitude} */
+ public static GeoRect nextBoxNear(double otherLatitude, double otherLongitude) {
+ GeoUtils.checkLongitude(otherLongitude);
+ GeoUtils.checkLongitude(otherLongitude);
+ return nextBoxInternal(nextLatitudeNear(otherLatitude), nextLatitudeNear(otherLatitude),
+ nextLongitudeNear(otherLongitude), nextLongitudeNear(otherLongitude), true);
+ }
+
+ /** returns next pseudorandom polygon */
+ public static double[][] nextPolygon() {
+ if (random().nextBoolean()) {
+ return surpriseMePolygon(null, null);
+ }
+
+ GeoRect box = nextBoxInternal(nextLatitude(), nextLatitude(), nextLongitude(), nextLongitude(), false);
+ if (random().nextBoolean()) {
+ // box
+ return boxPolygon(box);
+ } else {
+ // triangle
+ return trianglePolygon(box);
+ }
+ }
+
+ /** returns next pseudorandom polygon, kinda close to {@code otherLatitude} and {@code otherLongitude} */
+ public static double[][] nextPolygonNear(double otherLatitude, double otherLongitude) {
+ if (random().nextBoolean()) {
+ return surpriseMePolygon(otherLatitude, otherLongitude);
+ }
+
+ GeoRect box = nextBoxInternal(nextLatitudeNear(otherLatitude), nextLatitudeNear(otherLatitude),
+ nextLongitudeNear(otherLongitude), nextLongitudeNear(otherLongitude), false);
+ if (random().nextBoolean()) {
+ // box
+ return boxPolygon(box);
+ } else {
+ // triangle
+ return trianglePolygon(box);
+ }
+ }
+
+ private static GeoRect nextBoxInternal(double lat0, double lat1, double lon0, double lon1, boolean canCrossDateLine) {
+ if (lat1 < lat0) {
+ double x = lat0;
+ lat0 = lat1;
+ lat1 = x;
+ }
+
+ if (canCrossDateLine == false && lon1 < lon0) {
+ double x = lon0;
+ lon0 = lon1;
+ lon1 = x;
+ }
+
+ return new GeoRect(lat0, lat1, lon0, lon1);
+ }
+
+ private static double[][] boxPolygon(GeoRect box) {
+ assert box.crossesDateline() == false;
+ final double[] polyLats = new double[5];
+ final double[] polyLons = new double[5];
+ polyLats[0] = box.minLat;
+ polyLons[0] = box.minLon;
+ polyLats[1] = box.maxLat;
+ polyLons[1] = box.minLon;
+ polyLats[2] = box.maxLat;
+ polyLons[2] = box.maxLon;
+ polyLats[3] = box.minLat;
+ polyLons[3] = box.maxLon;
+ polyLats[4] = box.minLat;
+ polyLons[4] = box.minLon;
+ return new double[][] { polyLats, polyLons };
+ }
+
+ private static double[][] trianglePolygon(GeoRect box) {
+ assert box.crossesDateline() == false;
+ final double[] polyLats = new double[4];
+ final double[] polyLons = new double[4];
+ polyLats[0] = box.minLat;
+ polyLons[0] = box.minLon;
+ polyLats[1] = box.maxLat;
+ polyLons[1] = box.minLon;
+ polyLats[2] = box.maxLat;
+ polyLons[2] = box.maxLon;
+ polyLats[3] = box.minLat;
+ polyLons[3] = box.minLon;
+ return new double[][] { polyLats, polyLons };
+ }
+
+ /** Returns {polyLats, polyLons} double[] array */
+ private static double[][] surpriseMePolygon(Double otherLatitude, Double otherLongitude) {
+ // repeat until we get a poly that doesn't cross dateline:
+ newPoly:
+ while (true) {
+ //System.out.println("\nPOLY ITER");
+ final double centerLat;
+ final double centerLon;
+ if (otherLatitude == null) {
+ centerLat = nextLatitude();
+ centerLon = nextLongitude();
+ } else {
+ GeoUtils.checkLatitude(otherLatitude);
+ GeoUtils.checkLongitude(otherLongitude);
+ centerLat = nextLatitudeNear(otherLatitude);
+ centerLon = nextLongitudeNear(otherLongitude);
+ }
+
+ double radius = 0.1 + 20 * random().nextDouble();
+ double radiusDelta = random().nextDouble();
+
+ ArrayList<Double> lats = new ArrayList<>();
+ ArrayList<Double> lons = new ArrayList<>();
+ double angle = 0.0;
+ while (true) {
+ angle += random().nextDouble()*40.0;
+ //System.out.println(" angle " + angle);
+ if (angle > 360) {
+ break;
+ }
+ double len = radius * (1.0 - radiusDelta + radiusDelta * random().nextDouble());
+ //System.out.println(" len=" + len);
+ double lat = centerLat + len * Math.cos(Math.toRadians(angle));
+ double lon = centerLon + len * Math.sin(Math.toRadians(angle));
+ if (lon <= GeoUtils.MIN_LON_INCL || lon >= GeoUtils.MAX_LON_INCL) {
+ // cannot cross dateline: try again!
+ continue newPoly;
+ }
+ if (lat > 90) {
+ // cross the north pole
+ lat = 180 - lat;
+ lon = 180 - lon;
+ } else if (lat < -90) {
+ // cross the south pole
+ lat = -180 - lat;
+ lon = 180 - lon;
+ }
+ if (lon <= GeoUtils.MIN_LON_INCL || lon >= GeoUtils.MAX_LON_INCL) {
+ // cannot cross dateline: try again!
+ continue newPoly;
+ }
+ lats.add(lat);
+ lons.add(lon);
+
+ //System.out.println(" lat=" + lats.get(lats.size()-1) + " lon=" + lons.get(lons.size()-1));
+ }
+
+ // close it
+ lats.add(lats.get(0));
+ lons.add(lons.get(0));
+
+ double[] latsArray = new double[lats.size()];
+ double[] lonsArray = new double[lons.size()];
+ for(int i=0;i<lats.size();i++) {
+ latsArray[i] = lats.get(i);
+ lonsArray[i] = lons.get(i);
+ }
+ return new double[][] {latsArray, lonsArray};
+ }
+ }
+
/** Returns random double min to max or up to 1% outside of that range */
private static double randomRangeMaybeSlightlyOutside(double min, double max) {
return min + (random().nextDouble() + (0.5 - random().nextDouble()) * .02) * (max - min);