diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoExactCircle.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoExactCircle.java index 5726e6027f9..876b24f4a41 100644 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoExactCircle.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoExactCircle.java @@ -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 diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoExactCircleTest.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoExactCircleTest.java index 2f758f1169a..6f962142cd7 100644 --- a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoExactCircleTest.java +++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoExactCircleTest.java @@ -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); + } + }