mirror of https://github.com/apache/lucene.git
add randomized test for GeoUtils.circleToBBox
This commit is contained in:
parent
d700b149a5
commit
488591c419
|
@ -70,7 +70,7 @@ final class LatLonPointDistanceQuery extends Query {
|
|||
final GeoRect box2;
|
||||
|
||||
// crosses dateline: split
|
||||
if (box.maxLon < box.minLon) {
|
||||
if (box.crossesDateline()) {
|
||||
box1 = new GeoRect(-180.0, box.maxLon, box.minLat, box.maxLat);
|
||||
box2 = new GeoRect(box.minLon, 180.0, box.minLat, box.maxLat);
|
||||
} else {
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
*/
|
||||
package org.apache.lucene.search;
|
||||
|
||||
import org.apache.lucene.document.LatLonPoint;
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.LatLonPoint;
|
||||
import org.apache.lucene.spatial.util.BaseGeoPointTestCase;
|
||||
import org.apache.lucene.spatial.util.GeoDistanceUtils;
|
||||
import org.apache.lucene.spatial.util.GeoRect;
|
||||
import org.apache.lucene.spatial.util.GeoUtils;
|
||||
|
||||
public class TestLatLonPointQueries extends BaseGeoPointTestCase {
|
||||
// TODO: remove this!
|
||||
|
@ -146,4 +147,87 @@ public class TestLatLonPointQueries extends BaseGeoPointTestCase {
|
|||
final double d = GeoDistanceUtils.haversin(centerLat, centerLon, pointLat, pointLon);
|
||||
return d >= minRadiusMeters && d <= radiusMeters;
|
||||
}
|
||||
|
||||
/** Returns random double min to max or up to 1% outside of that range */
|
||||
private double randomRangeMaybeSlightlyOutside(double min, double max) {
|
||||
return min + (random().nextDouble() + (0.5 - random().nextDouble()) * .02) * (max - min);
|
||||
}
|
||||
|
||||
// We rely heavily on GeoUtils.circleToBBox so we test it here:
|
||||
public void testRandomCircleToBBox() throws Exception {
|
||||
int iters = atLeast(1000);
|
||||
for(int iter=0;iter<iters;iter++) {
|
||||
|
||||
boolean useSmallRanges = random().nextBoolean();
|
||||
|
||||
double radiusMeters;
|
||||
|
||||
double centerLat = randomLat(useSmallRanges);
|
||||
double centerLon = randomLon(useSmallRanges);
|
||||
|
||||
if (useSmallRanges) {
|
||||
// Approx 4 degrees lon at the equator:
|
||||
radiusMeters = random().nextDouble() * 444000;
|
||||
} else {
|
||||
radiusMeters = random().nextDouble() * 50000000;
|
||||
}
|
||||
|
||||
// TODO: randomly quantize radius too, to provoke exact math errors?
|
||||
|
||||
GeoRect bbox = GeoUtils.circleToBBox(centerLon, centerLat, radiusMeters);
|
||||
|
||||
int numPointsToTry = 1000;
|
||||
for(int i=0;i<numPointsToTry;i++) {
|
||||
|
||||
double lat;
|
||||
double lon;
|
||||
|
||||
if (random().nextBoolean()) {
|
||||
lat = randomLat(useSmallRanges);
|
||||
lon = randomLon(useSmallRanges);
|
||||
} else {
|
||||
// pick a lat/lon within the bbox or "slightly" outside it to try to improve test efficiency
|
||||
lat = quantizeLat(GeoUtils.normalizeLat(randomRangeMaybeSlightlyOutside(bbox.minLat, bbox.maxLat)));
|
||||
if (bbox.crossesDateline()) {
|
||||
if (random().nextBoolean()) {
|
||||
lon = quantizeLon(GeoUtils.normalizeLon(randomRangeMaybeSlightlyOutside(bbox.maxLon, -180)));
|
||||
} else {
|
||||
lon = quantizeLon(GeoUtils.normalizeLon(randomRangeMaybeSlightlyOutside(0, bbox.minLon)));
|
||||
}
|
||||
} else {
|
||||
lon = quantizeLon(GeoUtils.normalizeLon(randomRangeMaybeSlightlyOutside(bbox.minLon, bbox.maxLon)));
|
||||
}
|
||||
}
|
||||
|
||||
double distanceMeters = GeoDistanceUtils.haversin(centerLat, centerLon, lat, lon);
|
||||
|
||||
// Haversin says it's within the circle:
|
||||
boolean haversinSays = distanceMeters <= radiusMeters;
|
||||
|
||||
// BBox says its within the box:
|
||||
boolean bboxSays;
|
||||
if (bbox.crossesDateline()) {
|
||||
if (lat >= bbox.minLat && lat <= bbox.maxLat) {
|
||||
bboxSays = lon <= bbox.maxLon || lon >= bbox.minLon;
|
||||
} else {
|
||||
bboxSays = false;
|
||||
}
|
||||
} else {
|
||||
bboxSays = lat >= bbox.minLat && lat <= bbox.maxLat && lon >= bbox.minLon && lon <= bbox.maxLon;
|
||||
}
|
||||
|
||||
if (haversinSays) {
|
||||
if (bboxSays == false) {
|
||||
System.out.println("small=" + useSmallRanges + " centerLat=" + centerLat + " cetnerLon=" + centerLon + " radiusMeters=" + radiusMeters);
|
||||
System.out.println(" bbox: lat=" + bbox.minLat + " to " + bbox.maxLat + " lon=" + bbox.minLon + " to " + bbox.maxLon);
|
||||
System.out.println(" point: lat=" + lat + " lon=" + lon);
|
||||
System.out.println(" haversin: " + distanceMeters);
|
||||
fail("point was within the distance according to haversin, but the bbox doesn't contain it");
|
||||
}
|
||||
} else {
|
||||
// it's fine if haversin said it was outside the radius and bbox said it was inside the box
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,4 +70,9 @@ public class GeoRect {
|
|||
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
/** Returns true if this bounding box crosses the dateline */
|
||||
public boolean crossesDateline() {
|
||||
return maxLon < minLon;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue