mirror of https://github.com/apache/lucene.git
LUCENE-8257: All edges have a backing plane, so edge membership doesn't bleed through to the opposite side of the world.
This commit is contained in:
parent
72ee0f64d4
commit
4ee92c22a4
|
@ -590,6 +590,8 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
}
|
||||
}
|
||||
|
||||
private final static double[] halfProportions = new double[]{0.5};
|
||||
|
||||
/**
|
||||
* An instance of this class describes a single edge, and includes what is necessary to reliably determine intersection
|
||||
* in the context of the even/odd algorithm used.
|
||||
|
@ -600,6 +602,7 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
public final GeoPoint[] notablePoints;
|
||||
public final SidedPlane startPlane;
|
||||
public final SidedPlane endPlane;
|
||||
public final SidedPlane backingPlane;
|
||||
public final Plane plane;
|
||||
public final XYZBounds planeBounds;
|
||||
public Edge previous = null;
|
||||
|
@ -612,13 +615,19 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
this.plane = new Plane(startPoint, endPoint);
|
||||
this.startPlane = new SidedPlane(endPoint, plane, startPoint);
|
||||
this.endPlane = new SidedPlane(startPoint, plane, endPoint);
|
||||
final GeoPoint interpolationPoint = plane.interpolate(startPoint, endPoint, halfProportions)[0];
|
||||
this.backingPlane = new SidedPlane(interpolationPoint, interpolationPoint, 0.0);
|
||||
this.planeBounds = new XYZBounds();
|
||||
this.planeBounds.addPoint(startPoint);
|
||||
this.planeBounds.addPoint(endPoint);
|
||||
this.planeBounds.addPlane(pm, this.plane, this.startPlane, this.endPlane);
|
||||
this.planeBounds.addPlane(pm, this.plane, this.startPlane, this.endPlane, this.backingPlane);
|
||||
//System.err.println("Recording edge "+this+" from "+startPoint+" to "+endPoint+"; bounds = "+planeBounds);
|
||||
}
|
||||
|
||||
public boolean isWithin(final double thePointX, final double thePointY, final double thePointZ) {
|
||||
return plane.evaluateIsZero(thePointX, thePointY, thePointZ) && startPlane.isWithin(thePointX, thePointY, thePointZ) && endPlane.isWithin(thePointX, thePointY, thePointZ) && backingPlane.isWithin(thePointX, thePointY, thePointZ);
|
||||
}
|
||||
|
||||
// Hashcode and equals are system default!!
|
||||
}
|
||||
|
||||
|
@ -945,7 +954,7 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
@Override
|
||||
public boolean matches(final Edge edge) {
|
||||
// Early exit if the point is on the edge.
|
||||
if (edge.plane.evaluateIsZero(thePointX, thePointY, thePointZ) && edge.startPlane.isWithin(thePointX, thePointY, thePointZ) && edge.endPlane.isWithin(thePointX, thePointY, thePointZ)) {
|
||||
if (edge.isWithin(thePointX, thePointY, thePointZ)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1041,7 +1050,7 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
@Override
|
||||
public boolean matches(final Edge edge) {
|
||||
// Early exit if the point is on the edge.
|
||||
if (edge.plane.evaluateIsZero(thePointX, thePointY, thePointZ) && edge.startPlane.isWithin(thePointX, thePointY, thePointZ) && edge.endPlane.isWithin(thePointX, thePointY, thePointZ)) {
|
||||
if (edge.isWithin(thePointX, thePointY, thePointZ)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1289,7 +1298,7 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
@Override
|
||||
public boolean matches(final Edge edge) {
|
||||
// Early exit if the point is on the edge, in which case we accidentally discovered the answer.
|
||||
if (edge.plane.evaluateIsZero(thePointX, thePointY, thePointZ) && edge.startPlane.isWithin(thePointX, thePointY, thePointZ) && edge.endPlane.isWithin(thePointX, thePointY, thePointZ)) {
|
||||
if (edge.isWithin(thePointX, thePointY, thePointZ)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1587,4 +1587,24 @@ shape:
|
|||
assertTrue(polygon.isWithin(point) == largePolygon.isWithin(point));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLUCENE8257() {
|
||||
//POLYGON((12.9610296281349 -8.35317290232106,15.448601008878832 -3.990004427754539,22.375905319231205 0.2308875600810982,-13.473550791109867 30.10483127471788,-17.854443360411242 33.07441476406424,-3.928621142543736E-11 4.688559453373203E-11,0.0 -5.546974900361278E-104,12.9610296281349 -8.35317290232106))
|
||||
final List<GeoPoint> points = new ArrayList<>();
|
||||
points.add(new GeoPoint(PlanetModel.WGS84, Geo3DUtil.fromDegrees(-8.35317290232106), Geo3DUtil.fromDegrees(12.9610296281349)));
|
||||
points.add(new GeoPoint(PlanetModel.WGS84, Geo3DUtil.fromDegrees(-3.990004427754539), Geo3DUtil.fromDegrees(15.448601008878832)));
|
||||
points.add(new GeoPoint(PlanetModel.WGS84, Geo3DUtil.fromDegrees(0.2308875600810982), Geo3DUtil.fromDegrees(22.375905319231205)));
|
||||
points.add(new GeoPoint(PlanetModel.WGS84, Geo3DUtil.fromDegrees(30.10483127471788), Geo3DUtil.fromDegrees(-13.473550791109867)));
|
||||
points.add(new GeoPoint(PlanetModel.WGS84, Geo3DUtil.fromDegrees(33.07441476406424), Geo3DUtil.fromDegrees(-17.854443360411242)));
|
||||
points.add(new GeoPoint(PlanetModel.WGS84, Geo3DUtil.fromDegrees(4.688559453373203E-11), Geo3DUtil.fromDegrees(-3.928621142543736E-11)));
|
||||
points.add(new GeoPoint(PlanetModel.WGS84, Geo3DUtil.fromDegrees(-5.546974900361278E-104), Geo3DUtil.fromDegrees(0.0)));
|
||||
final GeoPolygonFactory.PolygonDescription description = new GeoPolygonFactory.PolygonDescription(points);
|
||||
final GeoPolygon polygon = GeoPolygonFactory.makeGeoPolygon(PlanetModel.WGS84, description);
|
||||
final GeoPolygon largePolygon = GeoPolygonFactory.makeLargeGeoPolygon(PlanetModel.WGS84, Collections.singletonList(description));
|
||||
|
||||
//POINT(-179.99999999999997 -9.638811778842766E-12)
|
||||
final GeoPoint point = new GeoPoint(PlanetModel.WGS84, Geo3DUtil.fromDegrees(-9.638811778842766E-12), Geo3DUtil.fromDegrees(-179.99999999999997));
|
||||
assertTrue(polygon.isWithin(point) == largePolygon.isWithin(point));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue