mirror of https://github.com/apache/lucene.git
LUCENE-7185: add proper tests for grid bugs found here, and fix related bugs still lurking
This commit is contained in:
parent
fe85885868
commit
acf0a57940
|
@ -22,8 +22,6 @@ import org.apache.lucene.util.FixedBitSet;
|
||||||
|
|
||||||
import static org.apache.lucene.geo.GeoEncodingUtils.decodeLatitude;
|
import static org.apache.lucene.geo.GeoEncodingUtils.decodeLatitude;
|
||||||
import static org.apache.lucene.geo.GeoEncodingUtils.decodeLongitude;
|
import static org.apache.lucene.geo.GeoEncodingUtils.decodeLongitude;
|
||||||
import static org.apache.lucene.geo.GeoEncodingUtils.encodeLatitude;
|
|
||||||
import static org.apache.lucene.geo.GeoEncodingUtils.encodeLongitude;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a temporary hack, until some polygon methods have better performance!
|
* This is a temporary hack, until some polygon methods have better performance!
|
||||||
|
@ -80,8 +78,10 @@ final class LatLonGrid {
|
||||||
long latitudeRange = maxLat - (long) minLat;
|
long latitudeRange = maxLat - (long) minLat;
|
||||||
long longitudeRange = maxLon - (long) minLon;
|
long longitudeRange = maxLon - (long) minLon;
|
||||||
|
|
||||||
if (latitudeRange < GRID_SIZE || longitudeRange < GRID_SIZE) {
|
// if the range is too small, we can't divide it up in our grid nicely.
|
||||||
// don't complicate fill right now if you pass e.g. emptyish stuff: make an "empty grid"
|
// in this case of a tiny polygon, we just make an empty grid instead of complicating/slowing down code.
|
||||||
|
final long minRange = (GRID_SIZE - 1) * (GRID_SIZE - 1);
|
||||||
|
if (latitudeRange < minRange || longitudeRange < minRange) {
|
||||||
latPerCell = lonPerCell = Long.MAX_VALUE;
|
latPerCell = lonPerCell = Long.MAX_VALUE;
|
||||||
} else {
|
} else {
|
||||||
// we spill over the edge of the bounding box in each direction a bit,
|
// we spill over the edge of the bounding box in each direction a bit,
|
||||||
|
@ -160,7 +160,9 @@ final class LatLonGrid {
|
||||||
long lonRel = longitude - (long) minLon;
|
long lonRel = longitude - (long) minLon;
|
||||||
|
|
||||||
int latIndex = (int) (latRel / latPerCell);
|
int latIndex = (int) (latRel / latPerCell);
|
||||||
|
assert latIndex < GRID_SIZE;
|
||||||
int lonIndex = (int) (lonRel / lonPerCell);
|
int lonIndex = (int) (lonRel / lonPerCell);
|
||||||
|
assert lonIndex < GRID_SIZE;
|
||||||
return latIndex * GRID_SIZE + lonIndex;
|
return latIndex * GRID_SIZE + lonIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.apache.lucene.document;
|
package org.apache.lucene.document;
|
||||||
|
|
||||||
import org.apache.lucene.geo.GeoTestUtil;
|
import org.apache.lucene.geo.GeoTestUtil;
|
||||||
|
import org.apache.lucene.geo.GeoUtils;
|
||||||
import org.apache.lucene.geo.Polygon;
|
import org.apache.lucene.geo.Polygon;
|
||||||
import org.apache.lucene.geo.Rectangle;
|
import org.apache.lucene.geo.Rectangle;
|
||||||
import org.apache.lucene.util.LuceneTestCase;
|
import org.apache.lucene.util.LuceneTestCase;
|
||||||
|
@ -32,7 +33,7 @@ public class TestLatLonGrid extends LuceneTestCase {
|
||||||
|
|
||||||
/** If the grid returns true, then any point in that cell should return true as well */
|
/** If the grid returns true, then any point in that cell should return true as well */
|
||||||
public void testRandom() throws Exception {
|
public void testRandom() throws Exception {
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 1000; i++) {
|
||||||
Polygon polygon = GeoTestUtil.nextPolygon();
|
Polygon polygon = GeoTestUtil.nextPolygon();
|
||||||
Rectangle box = Rectangle.fromPolygon(new Polygon[] { polygon });
|
Rectangle box = Rectangle.fromPolygon(new Polygon[] { polygon });
|
||||||
int minLat = encodeLatitude(box.minLat);
|
int minLat = encodeLatitude(box.minLat);
|
||||||
|
@ -52,4 +53,54 @@ public class TestLatLonGrid extends LuceneTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testGrowingPolygon() {
|
||||||
|
double centerLat = -80.0 + random().nextDouble() * 160.0;
|
||||||
|
double centerLon = -170.0 + random().nextDouble() * 340.0;
|
||||||
|
double radiusMeters = 0.0;
|
||||||
|
for(int i=0;i<10;i++) {
|
||||||
|
radiusMeters = Math.nextUp(radiusMeters);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start with a miniscule polygon, and grow it:
|
||||||
|
int gons = TestUtil.nextInt(random(), 4, 10);
|
||||||
|
while (radiusMeters < GeoUtils.EARTH_MEAN_RADIUS_METERS * Math.PI / 2.0 + 1.0) {
|
||||||
|
Polygon polygon;
|
||||||
|
try {
|
||||||
|
polygon = GeoTestUtil.createRegularPolygon(centerLat, centerLon, radiusMeters, gons);
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
// OK: we made a too-big poly and it crossed a pole or dateline
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
radiusMeters *= 1.1;
|
||||||
|
|
||||||
|
Rectangle box = Rectangle.fromPolygon(new Polygon[] { polygon });
|
||||||
|
int minLat = encodeLatitude(box.minLat);
|
||||||
|
int maxLat = encodeLatitude(box.maxLat);
|
||||||
|
int minLon = encodeLongitude(box.minLon);
|
||||||
|
int maxLon = encodeLongitude(box.maxLon);
|
||||||
|
LatLonGrid grid = new LatLonGrid(minLat, maxLat, minLon, maxLon, polygon);
|
||||||
|
// we are in integer space... but exhaustive testing is slow!
|
||||||
|
for (int j = 0; j < 1000; j++) {
|
||||||
|
int lat = TestUtil.nextInt(random(), minLat, maxLat);
|
||||||
|
int lon = TestUtil.nextInt(random(), minLon, maxLon);
|
||||||
|
|
||||||
|
boolean expected = polygon.contains(decodeLatitude(lat),
|
||||||
|
decodeLongitude(lon));
|
||||||
|
boolean actual = grid.contains(lat, lon);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** create ever-increasing grids and check that too-small polygons don't blow it up */
|
||||||
|
public void testTinyGrids() {
|
||||||
|
double ZERO = decodeLatitude(0);
|
||||||
|
double ONE = decodeLatitude(1);
|
||||||
|
Polygon tiny = new Polygon(new double[] { ZERO, ZERO, ONE, ONE, ZERO }, new double[] { ZERO, ONE, ONE, ZERO, ZERO });
|
||||||
|
for (int max = 1; max < 500000; max++) {
|
||||||
|
LatLonGrid grid = new LatLonGrid(0, max, 0, max, tiny);
|
||||||
|
assertEquals(tiny.contains(decodeLatitude(max), decodeLongitude(max)), grid.contains(max, max));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue