LUCENE-6535: Fix Geo3D bug in LUCENE-6520

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1684491 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
David Wayne Smiley 2015-06-09 18:08:04 +00:00
parent 5c9d550eec
commit 922a102a92
2 changed files with 39 additions and 2 deletions

View File

@ -120,8 +120,12 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
final SidedPlane candidate4 = SidedPlane.constructNormalizedThreePointSidedPlane(currentSegment.start, prevSegment.LRHC, prevSegment.URHC, currentSegment.ULHC);
if (candidate1 == null && candidate2 == null && candidate3 == null && candidate4 == null) {
// The planes are identical. We don't need a circle at all. Special constructor...
endPoints.add(new SegmentEndpoint(currentSegment.start));
// The planes are identical. We wouldn't need a circle at all except for the possibility of
// backing up, which is hard to detect here.
final SegmentEndpoint midEndpoint = new SegmentEndpoint(currentSegment.start,
prevSegment.endCutoffPlane, currentSegment.startCutoffPlane, currentSegment.ULHC, currentSegment.LLHC);
//don't need a circle at all. Special constructor...
endPoints.add(midEndpoint);
} else {
endPoints.add(new SegmentEndpoint(currentSegment.start,
prevSegment.endCutoffPlane, currentSegment.startCutoffPlane,
@ -414,6 +418,7 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
* Note well: This is not necessarily a circle. There are four cases:
* (1) The path consists of a single endpoint. In this case, we build a simple circle with the proper cutoff offset.
* (2) This is the end of a path. The circle plane must be constructed to go through two supplied points and be perpendicular to a connecting plane.
* (2.5) Intersection, but the path on both sides is linear. We generate a circle, but we use the cutoff planes to limit its influence in the straight line case.
* (3) This is an intersection in a path. We are supplied FOUR planes. If there are intersections within bounds for both upper and lower, then
* we generate no circle at all. If there is one intersection only, then we generate a plane that includes that intersection, as well as the remaining
* cutoff plane/edge plane points.
@ -458,6 +463,18 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
// To construct the plane, we now just need D, which is simply the negative of the evaluation of the circle normal vector at one of the points.
this.circlePlane = SidedPlane.constructNormalizedPerpendicularSidedPlane(point, cutoffPlane, topEdgePoint, bottomEdgePoint);
}
/** Constructor for case (2.5).
* Generate an endpoint, given two cutoff planes plus upper and lower edge points.
*/
public SegmentEndpoint(final GeoPoint point,
final SidedPlane cutoffPlane1, final SidedPlane cutoffPlane2, final GeoPoint topEdgePoint, final GeoPoint bottomEdgePoint) {
this.point = point;
this.cutoffPlanes = new Membership[]{new SidedPlane(cutoffPlane1), new SidedPlane(cutoffPlane2)};
this.notablePoints = new GeoPoint[]{topEdgePoint, bottomEdgePoint};
// To construct the plane, we now just need D, which is simply the negative of the evaluation of the circle normal vector at one of the points.
this.circlePlane = SidedPlane.constructNormalizedPerpendicularSidedPlane(point, cutoffPlane1, topEdgePoint, bottomEdgePoint);
}
/** Constructor for case (3).
* Generate an endpoint for an intersection, given four points.

View File

@ -92,6 +92,26 @@ public class Geo3dRptTest extends RandomSpatialOpStrategyTestCase {
testOperation(rect,SpatialOperation.Intersects,triangle, false);
}
@Test
public void testFailureLucene6535() throws IOException {
setupStrategy();
final List<GeoPoint> points = new ArrayList<>();
points.add(new GeoPoint(PlanetModel.SPHERE, 18 * DEGREES_TO_RADIANS, -27 * DEGREES_TO_RADIANS));
points.add(new GeoPoint(PlanetModel.SPHERE, -57 * DEGREES_TO_RADIANS, 146 * DEGREES_TO_RADIANS));
points.add(new GeoPoint(PlanetModel.SPHERE, 14 * DEGREES_TO_RADIANS, -180 * DEGREES_TO_RADIANS));
points.add(new GeoPoint(PlanetModel.SPHERE, -15 * DEGREES_TO_RADIANS, 153 * DEGREES_TO_RADIANS));
final GeoPath path = new GeoPath(PlanetModel.SPHERE, 29 * DEGREES_TO_RADIANS);
path.addPoint(55.0 * DEGREES_TO_RADIANS, -26.0 * DEGREES_TO_RADIANS);
path.addPoint(-90.0 * DEGREES_TO_RADIANS, 0.0);
path.addPoint(54.0 * DEGREES_TO_RADIANS, 165.0 * DEGREES_TO_RADIANS);
path.addPoint(-90.0 * DEGREES_TO_RADIANS, 0.0);
path.done();
final Shape shape = new Geo3dShape(path,ctx);
final Rectangle rect = ctx.makeRectangle(131, 143, 39, 54);
testOperation(rect,SpatialOperation.Intersects,shape,true);
}
@Test
@Repeat(iterations = 10)
public void testOperations() throws IOException {