LUCENE-8080: Detect when we are constructing a bogus exact circle, and throw an IllegalArgumentException in that case. Committed on behalf of Ignacio Vera.

This commit is contained in:
Karl Wright 2017-12-08 05:41:11 -05:00
parent cd30dabe37
commit 18f12fdb28
2 changed files with 34 additions and 15 deletions

View File

@ -77,17 +77,16 @@ class GeoExactCircle extends GeoBaseCircle {
final GeoPoint eastPoint = planetModel.surfacePointOnBearing(center, cutoffAngle, Math.PI * 0.5);
final GeoPoint westPoint = planetModel.surfacePointOnBearing(center, cutoffAngle, Math.PI * 1.5);
final boolean mustSplit = cutoffAngle > Math.PI * 0.5;
final GeoPoint edgePoint;
if (planetModel.c > planetModel.ab) {
// z can be greater than x or y, so ellipse is longer in height than width
slices.add(new ApproximationSlice(center, eastPoint, Math.PI * 0.5, westPoint, Math.PI * -0.5, northPoint, 0.0, mustSplit));
slices.add(new ApproximationSlice(center, westPoint, Math.PI * 1.5, eastPoint, Math.PI * 0.5, southPoint, Math.PI, mustSplit));
slices.add(new ApproximationSlice(center, eastPoint, Math.PI * 0.5, westPoint, Math.PI * -0.5, northPoint, 0.0, true));
slices.add(new ApproximationSlice(center, westPoint, Math.PI * 1.5, eastPoint, Math.PI * 0.5, southPoint, Math.PI, true));
edgePoint = eastPoint;
} else {
// z will be less than x or y, so ellipse is shorter than it is tall
slices.add(new ApproximationSlice(center, northPoint, 0.0, southPoint, Math.PI, eastPoint, Math.PI * 0.5, mustSplit));
slices.add(new ApproximationSlice(center, southPoint, Math.PI, northPoint, Math.PI * 2.0, westPoint, Math.PI * 1.5, mustSplit));
slices.add(new ApproximationSlice(center, northPoint, 0.0, southPoint, Math.PI, eastPoint, Math.PI * 0.5, true));
slices.add(new ApproximationSlice(center, southPoint, Math.PI, northPoint, Math.PI * 2.0, westPoint, Math.PI * 1.5, true));
edgePoint = northPoint;
}
//System.out.println("Edgepoint = " + edgePoint);
@ -283,8 +282,10 @@ class GeoExactCircle extends GeoBaseCircle {
if (this.plane == null) {
throw new IllegalArgumentException("Either circle is too small or accuracy is too high; could not construct a plane with endPoint1="+endPoint1+" bearing "+point1Bearing+", endPoint2="+endPoint2+" bearing "+point2Bearing+", middle="+middlePoint+" bearing "+middlePointBearing);
}
if (plane.isWithin(center) == false || !plane.evaluateIsZero(endPoint1) || !plane.evaluateIsZero(endPoint2) || !plane.evaluateIsZero(middlePoint))
throw new IllegalStateException("SidedPlane constructor built a bad plane!!");
if (this.plane.isWithin(-center.x, -center.y, -center.z)) {
//Plane is bogus, we cannot build the circle
throw new IllegalArgumentException("Could not construct a valid plane for this planet model with endPoint1="+endPoint1+" bearing "+point1Bearing+", endPoint2="+endPoint2+" bearing "+point2Bearing+", middle="+middlePoint+" bearing "+middlePointBearing);
}
}
@Override

View File

@ -54,8 +54,6 @@ public class GeoExactCircleTest extends RandomGeo3dShapeGenerator{
@Test
public void testSurfacePointOnBearingScale(){
double ab = 1.6;
double c = 0.7;
PlanetModel p1 = PlanetModel.WGS84;
PlanetModel p2 = new PlanetModel(0.5 * PlanetModel.WGS84.ab, 0.5 * PlanetModel.WGS84.c );
GeoPoint point1P1 = new GeoPoint(p1, 0, 0);
@ -93,9 +91,18 @@ public class GeoExactCircleTest extends RandomGeo3dShapeGenerator{
@Test
@Repeat(iterations = 100)
public void RandomPointBearingCardinalTest(){
double ab = random().nextDouble() * 0.6 + 0.9;
double c = random().nextDouble() * 0.6 + 0.9 ;
PlanetModel planetModel = new PlanetModel(ab, c);
//surface distance calculations methods start not converging when
//planet flattening > 0.4
PlanetModel planetModel;
do {
double ab = random().nextDouble() * 2;
double c = random().nextDouble() * 2;
if (random().nextBoolean()) {
planetModel = new PlanetModel(ab, c);
} else {
planetModel = new PlanetModel(c, ab);
}
} while (Math.abs(planetModel.flattening) > 0.4);
GeoPoint center = randomGeoPoint(planetModel);
double radius = random().nextDouble() * 0.9 * Math.PI;
checkBearingPoint(planetModel, center, radius, 0);
@ -133,7 +140,7 @@ public class GeoExactCircleTest extends RandomGeo3dShapeGenerator{
public void exactCircleLargeTest(){
boolean success = true;
try {
GeoCircle circle = GeoCircleFactory.makeExactGeoCircle(new PlanetModel(0.5, 0.7), 0.25 * Math.PI, 0,0.35 * Math.PI, 1e-12);
GeoCircle circle = GeoCircleFactory.makeExactGeoCircle(new PlanetModel(0.99, 1.05), 0.25 * Math.PI, 0,0.35 * Math.PI, 1e-12);
} catch (IllegalArgumentException e) {
success = false;
}
@ -174,8 +181,8 @@ public class GeoExactCircleTest extends RandomGeo3dShapeGenerator{
*/
@Test
@Repeat(iterations = 100)
public void testRandom_LUCENE8054() {
PlanetModel planetModel = PlanetModel.WGS84;
public void testRandomLUCENE8054() {
PlanetModel planetModel = randomPlanetModel();
GeoCircle circle1 = (GeoCircle) randomGeoAreaShape(EXACT_CIRCLE, planetModel);
// new radius, a bit smaller than the generated one!
double radius = circle1.getRadius() * (1 - 0.01 * random().nextDouble());
@ -232,4 +239,15 @@ public class GeoExactCircleTest extends RandomGeo3dShapeGenerator{
assertTrue(circle1.getRelationship(circle2) != GeoArea.DISJOINT);
}
public void testLUCENE8080() {
PlanetModel planetModel = new PlanetModel(1.6304230055804751, 1.0199671157571204);
boolean fail = false;
try {
GeoCircle circle = GeoCircleFactory.makeExactGeoCircle(planetModel, 0.8853814403571284, 0.9784990176851283, 0.9071033527030907, 1e-11);
} catch (IllegalArgumentException e) {
fail = true;
}
assertTrue(fail);
}
}