From 49583ed13da97cd11c8b9d1b3a88079175a6c69d Mon Sep 17 00:00:00 2001 From: Karl Wright Date: Tue, 26 Sep 2017 03:20:32 -0400 Subject: [PATCH] LUCENE-7970: Handle the case where we generate only a pair of identical planes, as might happen when the center is near a pole. --- .../lucene/spatial3d/geom/GeoExactCircle.java | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) 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 b6ae081abf9..03eb5ce8444 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 @@ -119,8 +119,9 @@ class GeoExactCircle extends GeoBaseCircle { this.notableEdgePoints = null; } else { this.circlePlanes = new ArrayList<>(); - this.notableEdgePoints = new ArrayList<>(); - this.eitherBounds = new HashMap<>(); + // If it turns out that there's only one circle plane, this array will be populated but unused + final List notableEdgePoints = new ArrayList<>(); + // We construct approximation planes until we have a low enough error estimate final List slices = new ArrayList<>(100); // Construct four cardinal points, and then we'll build the first two planes @@ -154,9 +155,11 @@ class GeoExactCircle extends GeoBaseCircle { final GeoPoint interpPoint2 = planetModel.surfacePointOnBearing(center, cutoffAngle, interpPoint2Bearing); // Is this point on the plane? (that is, is the approximation good enough?) if (Math.abs(thisSlice.plane.evaluate(interpPoint1)) < actualAccuracy && Math.abs(thisSlice.plane.evaluate(interpPoint2)) < actualAccuracy) { - // Good enough; add it to the list of planes - circlePlanes.add(thisSlice.plane); - notableEdgePoints.add(new GeoPoint[]{thisSlice.endPoint1, thisSlice.endPoint2}); + // Good enough; add it to the list of planes, unless it was identical to the previous plane + if (circlePlanes.size() == 0 || !circlePlanes.get(circlePlanes.size()-1).isNumericallyIdentical(thisSlice.plane)) { + circlePlanes.add(thisSlice.plane); + notableEdgePoints.add(new GeoPoint[]{thisSlice.endPoint1, thisSlice.endPoint2}); + } } else { // Split the plane into two, and add it back to the end slices.add(new ApproximationSlice(center, @@ -173,11 +176,18 @@ class GeoExactCircle extends GeoBaseCircle { //System.out.println("Number of planes needed: "+circlePlanes.size()); // Compute bounds - for (int i = 0; i < circlePlanes.size(); i++) { - final SidedPlane thisPlane = circlePlanes.get(i); - final SidedPlane previousPlane = (i == 0)?circlePlanes.get(circlePlanes.size()-1):circlePlanes.get(i-1); - final SidedPlane nextPlane = (i == circlePlanes.size()-1)?circlePlanes.get(0):circlePlanes.get(i+1); - eitherBounds.put(thisPlane, new EitherBound(previousPlane, nextPlane)); + if (circlePlanes.size() == 1) { + this.eitherBounds = null; + this.notableEdgePoints = null; + } else { + this.notableEdgePoints = notableEdgePoints; + this.eitherBounds = new HashMap<>(circlePlanes.size()); + for (int i = 0; i < circlePlanes.size(); i++) { + final SidedPlane thisPlane = circlePlanes.get(i); + final SidedPlane previousPlane = (i == 0)?circlePlanes.get(circlePlanes.size()-1):circlePlanes.get(i-1); + final SidedPlane nextPlane = (i == circlePlanes.size()-1)?circlePlanes.get(0):circlePlanes.get(i+1); + eitherBounds.put(thisPlane, new EitherBound(previousPlane, nextPlane)); + } } } }