LUCENE-7173: Get the random nested polygon code working.

This commit is contained in:
Karl Wright 2016-04-06 18:57:00 -04:00
parent eda2a31959
commit 0163574f9c
1 changed files with 87 additions and 77 deletions

View File

@ -827,15 +827,14 @@ public class TestGeo3DPoint extends LuceneTestCase {
assertFalse(q.equals(Geo3DPoint.newShapeQuery("point", shape2))); assertFalse(q.equals(Geo3DPoint.newShapeQuery("point", shape2)));
} }
@Ignore
public void testComplexPolygons() { public void testComplexPolygons() {
final PlanetModel pm = PlanetModel.WGS84; final PlanetModel pm = PlanetModel.WGS84;
// Pick a random pole // Pick a random pole
final GeoPoint randomPole = new GeoPoint(pm, Math.toRadians(randomLat()), Math.toRadians(randomLon())); final GeoPoint randomPole = new GeoPoint(pm, Math.toRadians(randomLat()), Math.toRadians(randomLon()));
// Create a polygon that's less than 180 degrees // Create a polygon that's less than 180 degrees
final Polygon clockWise = makePoly(pm, randomPole, true); final Polygon clockWise = makePoly(pm, randomPole, true, true);
// Create a polygon that's greater than 180 degrees // Create a polygon that's greater than 180 degrees
final Polygon counterClockWise = makePoly(pm, randomPole, false); final Polygon counterClockWise = makePoly(pm, randomPole, false, true);
} }
@ -847,7 +846,7 @@ public class TestGeo3DPoint extends LuceneTestCase {
* doesn't do it because it's almost impossible to come up with nested ones of the proper * doesn't do it because it's almost impossible to come up with nested ones of the proper
* clockwise/counterclockwise rotation that way. * clockwise/counterclockwise rotation that way.
*/ */
protected Polygon makePoly(final PlanetModel pm, final GeoPoint pole, final boolean clockwiseDesired) { protected Polygon makePoly(final PlanetModel pm, final GeoPoint pole, final boolean clockwiseDesired, final boolean createHoles) {
// Polygon edges will be arranged around the provided pole, and holes will each have a pole selected within the parent // Polygon edges will be arranged around the provided pole, and holes will each have a pole selected within the parent
// polygon. // polygon.
final int pointCount = TestUtil.nextInt(random(), 3, 10); final int pointCount = TestUtil.nextInt(random(), 3, 10);
@ -857,6 +856,8 @@ public class TestGeo3DPoint extends LuceneTestCase {
// These are all picked in the context of the pole, // These are all picked in the context of the pole,
final double[] angles = new double[pointCount]; final double[] angles = new double[pointCount];
final double[] arcDistance = new double[pointCount]; final double[] arcDistance = new double[pointCount];
// Pick a set of points
while (true) {
double accumulatedAngle = 0.0; double accumulatedAngle = 0.0;
for (int i = 0; i < pointCount; i++) { for (int i = 0; i < pointCount; i++) {
final int remainingEdgeCount = pointCount - i; final int remainingEdgeCount = pointCount - i;
@ -891,19 +892,25 @@ public class TestGeo3DPoint extends LuceneTestCase {
final List<GeoPoint> polyPoints = convertToPoints(pm, pole, angles, arcDistance); final List<GeoPoint> polyPoints = convertToPoints(pm, pole, angles, arcDistance);
// Create the geo3d polygon, so we can test out our poles. // Create the geo3d polygon, so we can test out our poles.
GeoPolygon poly = GeoPolygonFactory.makeGeoPolygon(pm, polyPoints, null); final GeoPolygon poly;
try {
poly = GeoPolygonFactory.makeGeoPolygon(pm, polyPoints, null);
} catch (IllegalArgumentException e) {
// This is what happens when three adjacent points are colinear, so try again.
continue;
}
// Next, do some holes. No more than 2 of these. The poles for holes must always be within the polygon, so we're // Next, do some holes. No more than 2 of these. The poles for holes must always be within the polygon, so we're
// going to use Geo3D to help us select those given the points we just made. // going to use Geo3D to help us select those given the points we just made.
final int holeCount = TestUtil.nextInt(random(), 0, 2); final int holeCount = createHoles?TestUtil.nextInt(random(), 0, 2):0;
final Polygon[] holes = new Polygon[holeCount]; final List<Polygon> holeList = new ArrayList<>();
for (int i = 0; i < holeCount; i++) { for (int i = 0; i < holeCount; i++) {
// Choose a pole. The poly has to be within the polygon, but it also cannot be on the polygon edge. // Choose a pole. The poly has to be within the polygon, but it also cannot be on the polygon edge.
// We try indefinitely to find a good pole... // If we can't find a good pole we have to give it up and not do the hole.
while (true) { for (int k = 0; k < 500; k++) {
final GeoPoint poleChoice = new GeoPoint(pm, toRadians(randomLat()), toRadians(randomLon())); final GeoPoint poleChoice = new GeoPoint(pm, toRadians(randomLat()), toRadians(randomLon()));
if (!poly.isWithin(poleChoice)) { if (!poly.isWithin(poleChoice)) {
continue; continue;
@ -912,12 +919,12 @@ public class TestGeo3DPoint extends LuceneTestCase {
// After that we give up and pick a new pole. // After that we give up and pick a new pole.
boolean foundOne = false; boolean foundOne = false;
for (int j = 0; j < 100; j++) { for (int j = 0; j < 100; j++) {
final Polygon insidePoly = makePoly(pm, poleChoice, !clockwiseDesired); final Polygon insidePoly = makePoly(pm, poleChoice, !clockwiseDesired, false);
// Verify that the inside polygon is OK. If not, discard and repeat. // Verify that the inside polygon is OK. If not, discard and repeat.
if (!verifyPolygon(pm, insidePoly, poly)) { if (!verifyPolygon(pm, insidePoly, poly)) {
continue; continue;
} }
holes[i] = insidePoly; holeList.add(insidePoly);
foundOne = true; foundOne = true;
} }
if (foundOne) { if (foundOne) {
@ -926,6 +933,8 @@ public class TestGeo3DPoint extends LuceneTestCase {
} }
} }
final Polygon[] holes = holeList.toArray(new Polygon[0]);
// Finally, build the polygon and return it // Finally, build the polygon and return it
final double[] lats = new double[polyPoints.size() + 1]; final double[] lats = new double[polyPoints.size() + 1];
final double[] lons = new double[polyPoints.size() + 1]; final double[] lons = new double[polyPoints.size() + 1];
@ -938,6 +947,7 @@ public class TestGeo3DPoint extends LuceneTestCase {
lons[polyPoints.size()] = lons[0]; lons[polyPoints.size()] = lons[0];
return new Polygon(lats, lons, holes); return new Polygon(lats, lons, holes);
} }
}
protected static List<GeoPoint> convertToPoints(final PlanetModel pm, final GeoPoint pole, final double[] angles, final double[] arcDistances) { protected static List<GeoPoint> convertToPoints(final PlanetModel pm, final GeoPoint pole, final double[] angles, final double[] arcDistances) {
// To do the point rotations, we need the sine and cosine of the pole latitude and longitude. Get it here for performance. // To do the point rotations, we need the sine and cosine of the pole latitude and longitude. Get it here for performance.
@ -1035,7 +1045,7 @@ public class TestGeo3DPoint extends LuceneTestCase {
} }
protected static int legalIndex(int index, int size) { protected static int legalIndex(int index, int size) {
if (index > size) { if (index >= size) {
index -= size; index -= size;
} }
if (index < 0) { if (index < 0) {