mirror of https://github.com/apache/lucene.git
move tests from sandbox/ to spatial/ since they test GeoUtils methods (now with no unwanted quantization)
This commit is contained in:
parent
5da1ec91d0
commit
c9a197490d
|
@ -34,8 +34,6 @@ import org.apache.lucene.search.IndexSearcher;
|
|||
import org.apache.lucene.search.ScoreDoc;
|
||||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.TopDocs;
|
||||
import org.apache.lucene.spatial.util.GeoRect;
|
||||
import org.apache.lucene.spatial.util.GeoUtils;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.lucene.util.SloppyMath;
|
||||
|
@ -189,55 +187,4 @@ public class TestLatLonPointDistanceQuery extends LuceneTestCase {
|
|||
writer.close();
|
||||
dir.close();
|
||||
}
|
||||
|
||||
public void testBoundingBoxOpto() {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
double lat = -90 + 180.0 * random().nextDouble();
|
||||
double lon = -180 + 360.0 * random().nextDouble();
|
||||
double radius = 50000000 * random().nextDouble();
|
||||
GeoRect box = GeoUtils.circleToBBox(lon, lat, radius);
|
||||
final GeoRect box1;
|
||||
final GeoRect box2;
|
||||
if (box.crossesDateline()) {
|
||||
box1 = new GeoRect(-180, box.maxLon, box.minLat, box.maxLat);
|
||||
box2 = new GeoRect(box.minLon, 180, box.minLat, box.maxLat);
|
||||
} else {
|
||||
box1 = box;
|
||||
box2 = null;
|
||||
}
|
||||
|
||||
for (int j = 0; j < 10000; j++) {
|
||||
double lat2 = -90 + 180.0 * random().nextDouble();
|
||||
double lon2 = -180 + 360.0 * random().nextDouble();
|
||||
// if the point is within radius, then it should be in our bounding box
|
||||
if (SloppyMath.haversinMeters(lat, lon, lat2, lon2) <= radius) {
|
||||
assertTrue(lat >= box.minLat && lat <= box.maxLat);
|
||||
assertTrue(lon >= box1.minLon && lon <= box1.maxLon || (box2 != null && lon >= box2.minLon && lon <= box2.maxLon));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testHaversinOpto() {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
double lat = -90 + 180.0 * random().nextDouble();
|
||||
double lon = -180 + 360.0 * random().nextDouble();
|
||||
double radius = 50000000 * random().nextDouble();
|
||||
GeoRect box = GeoUtils.circleToBBox(lon, lat, radius);
|
||||
|
||||
if (box.maxLon - lon < 90 && lon - box.minLon < 90) {
|
||||
double minPartialDistance = Math.max(SloppyMath.haversinSortKey(lat, lon, lat, box.maxLon),
|
||||
SloppyMath.haversinSortKey(lat, lon, box.maxLat, lon));
|
||||
|
||||
for (int j = 0; j < 10000; j++) {
|
||||
double lat2 = -90 + 180.0 * random().nextDouble();
|
||||
double lon2 = -180 + 360.0 * random().nextDouble();
|
||||
// if the point is within radius, then it should be <= our sort key
|
||||
if (SloppyMath.haversinMeters(lat, lon, lat2, lon2) <= radius) {
|
||||
assertTrue(SloppyMath.haversinSortKey(lat, lon, lat2, lon2) <= minPartialDistance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,8 +27,6 @@ import org.apache.lucene.search.MatchAllDocsQuery;
|
|||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.SortField;
|
||||
import org.apache.lucene.search.TopDocs;
|
||||
import org.apache.lucene.spatial.util.GeoRect;
|
||||
import org.apache.lucene.spatial.util.GeoUtils;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.lucene.util.SloppyMath;
|
||||
|
@ -252,18 +250,4 @@ public class TestLatLonPointDistanceSort extends LuceneTestCase {
|
|||
writer.close();
|
||||
dir.close();
|
||||
}
|
||||
|
||||
/** Test infinite radius covers whole earth */
|
||||
public void testInfiniteRect() {
|
||||
for (int i = 0; i < 100000; i++) {
|
||||
double centerLat = -90 + 180.0 * random().nextDouble();
|
||||
double centerLon = -180 + 360.0 * random().nextDouble();
|
||||
GeoRect rect = GeoUtils.circleToBBox(centerLat, centerLon, Double.POSITIVE_INFINITY);
|
||||
assertEquals(-180.0, rect.minLon, 0.0D);
|
||||
assertEquals(180.0, rect.maxLon, 0.0D);
|
||||
assertEquals(-90.0, rect.minLat, 0.0D);
|
||||
assertEquals(90.0, rect.maxLat, 0.0D);
|
||||
assertFalse(rect.crossesDateline());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import org.apache.lucene.document.LatLonPoint;
|
|||
import org.apache.lucene.spatial.util.BaseGeoPointTestCase;
|
||||
import org.apache.lucene.spatial.util.GeoRect;
|
||||
import org.apache.lucene.spatial.util.GeoRelationUtils;
|
||||
import org.apache.lucene.spatial.util.GeoUtils;
|
||||
import org.apache.lucene.util.SloppyMath;
|
||||
|
||||
public class TestLatLonPointQueries extends BaseGeoPointTestCase {
|
||||
|
@ -103,87 +102,4 @@ public class TestLatLonPointQueries extends BaseGeoPointTestCase {
|
|||
final double d = SloppyMath.haversinMeters(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 = SloppyMath.haversinMeters(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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -563,4 +563,154 @@ public class TestGeoUtils extends LuceneTestCase {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 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 = GeoUtils.normalizeLat(randomRangeMaybeSlightlyOutside(bbox.minLat, bbox.maxLat));
|
||||
if (bbox.crossesDateline()) {
|
||||
if (random().nextBoolean()) {
|
||||
lon = GeoUtils.normalizeLon(randomRangeMaybeSlightlyOutside(bbox.maxLon, -180));
|
||||
} else {
|
||||
lon = GeoUtils.normalizeLon(randomRangeMaybeSlightlyOutside(0, bbox.minLon));
|
||||
}
|
||||
} else {
|
||||
lon = GeoUtils.normalizeLon(randomRangeMaybeSlightlyOutside(bbox.minLon, bbox.maxLon));
|
||||
}
|
||||
}
|
||||
|
||||
double distanceMeters = SloppyMath.haversinMeters(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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// similar to testRandomCircleToBBox, but different, less evil, maybe simpler
|
||||
public void testBoundingBoxOpto() {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
double lat = -90 + 180.0 * random().nextDouble();
|
||||
double lon = -180 + 360.0 * random().nextDouble();
|
||||
double radius = 50000000 * random().nextDouble();
|
||||
GeoRect box = GeoUtils.circleToBBox(lon, lat, radius);
|
||||
final GeoRect box1;
|
||||
final GeoRect box2;
|
||||
if (box.crossesDateline()) {
|
||||
box1 = new GeoRect(-180, box.maxLon, box.minLat, box.maxLat);
|
||||
box2 = new GeoRect(box.minLon, 180, box.minLat, box.maxLat);
|
||||
} else {
|
||||
box1 = box;
|
||||
box2 = null;
|
||||
}
|
||||
|
||||
for (int j = 0; j < 10000; j++) {
|
||||
double lat2 = -90 + 180.0 * random().nextDouble();
|
||||
double lon2 = -180 + 360.0 * random().nextDouble();
|
||||
// if the point is within radius, then it should be in our bounding box
|
||||
if (SloppyMath.haversinMeters(lat, lon, lat2, lon2) <= radius) {
|
||||
assertTrue(lat >= box.minLat && lat <= box.maxLat);
|
||||
assertTrue(lon >= box1.minLon && lon <= box1.maxLon || (box2 != null && lon >= box2.minLon && lon <= box2.maxLon));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// test we can use haversinSortKey() for distance queries.
|
||||
public void testHaversinOpto() {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
double lat = -90 + 180.0 * random().nextDouble();
|
||||
double lon = -180 + 360.0 * random().nextDouble();
|
||||
double radius = 50000000 * random().nextDouble();
|
||||
GeoRect box = GeoUtils.circleToBBox(lon, lat, radius);
|
||||
|
||||
if (box.maxLon - lon < 90 && lon - box.minLon < 90) {
|
||||
double minPartialDistance = Math.max(SloppyMath.haversinSortKey(lat, lon, lat, box.maxLon),
|
||||
SloppyMath.haversinSortKey(lat, lon, box.maxLat, lon));
|
||||
|
||||
for (int j = 0; j < 10000; j++) {
|
||||
double lat2 = -90 + 180.0 * random().nextDouble();
|
||||
double lon2 = -180 + 360.0 * random().nextDouble();
|
||||
// if the point is within radius, then it should be <= our sort key
|
||||
if (SloppyMath.haversinMeters(lat, lon, lat2, lon2) <= radius) {
|
||||
assertTrue(SloppyMath.haversinSortKey(lat, lon, lat2, lon2) <= minPartialDistance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Test infinite radius covers whole earth */
|
||||
public void testInfiniteRect() {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
double centerLat = -90 + 180.0 * random().nextDouble();
|
||||
double centerLon = -180 + 360.0 * random().nextDouble();
|
||||
GeoRect rect = GeoUtils.circleToBBox(centerLat, centerLon, Double.POSITIVE_INFINITY);
|
||||
assertEquals(-180.0, rect.minLon, 0.0D);
|
||||
assertEquals(180.0, rect.maxLon, 0.0D);
|
||||
assertEquals(-90.0, rect.minLat, 0.0D);
|
||||
assertEquals(90.0, rect.maxLat, 0.0D);
|
||||
assertFalse(rect.crossesDateline());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue