LUCENE-7402: If intersection computation falls off the world, bounds includes whole world.

This commit is contained in:
Karl Wright 2016-08-04 08:12:08 -04:00
parent 17797673f2
commit 2828f4e8e0
5 changed files with 50 additions and 4 deletions

View File

@ -121,4 +121,11 @@ public interface Bounds {
*/
public Bounds noBottomLatitudeBound();
/** Signal that there is no bound whatsoever.
* The bound is limited only by the constraints of the
* planet.
*@return the updated Bounds object.,
*/
public Bounds noBound(final PlanetModel planetModel);
}

View File

@ -253,6 +253,11 @@ public class LatLonBounds implements Bounds {
return this;
}
@Override
public Bounds noBound(final PlanetModel planetModel) {
return noLongitudeBound().noTopLatitudeBound().noBottomLatitudeBound();
}
// Protected methods
/** Update latitude bound.

View File

@ -1003,13 +1003,14 @@ public class Plane extends Vector {
* D - MINIMUM_RESOLUTION. Both are examined and intersection points determined.
*/
protected void findIntersectionBounds(final PlanetModel planetModel, final Bounds boundsInfo, final Plane q, final Membership... bounds) {
//System.out.println("Finding intersection bounds");
// Unnormalized, unchecked...
final double lineVectorX = y * q.z - z * q.y;
final double lineVectorY = z * q.x - x * q.z;
final double lineVectorZ = x * q.y - y * q.x;
if (Math.abs(lineVectorX) < MINIMUM_RESOLUTION && Math.abs(lineVectorY) < MINIMUM_RESOLUTION && Math.abs(lineVectorZ) < MINIMUM_RESOLUTION) {
// Degenerate case: parallel planes
//System.err.println(" planes are parallel - no intersection");
//System.out.println(" planes are parallel - no intersection");
return;
}
@ -1037,9 +1038,10 @@ public class Plane extends Vector {
final double denomXZ = this.x * q.z - this.z * q.x;
final double denomXY = this.x * q.y - this.y * q.x;
if (Math.abs(denomYZ) >= Math.abs(denomXZ) && Math.abs(denomYZ) >= Math.abs(denomXY)) {
//System.out.println("X biggest");
// X is the biggest, so our point will have x0 = 0.0
if (Math.abs(denomYZ) < MINIMUM_RESOLUTION_SQUARED) {
//System.err.println(" Denominator is zero: no intersection");
//System.out.println(" Denominator is zero: no intersection");
return;
}
final double denom = 1.0 / denomYZ;
@ -1061,9 +1063,10 @@ public class Plane extends Vector {
0.0, (-(this.D-MINIMUM_RESOLUTION) * q.z - this.z * -(q.D-MINIMUM_RESOLUTION)) * denom, (this.y * -(q.D-MINIMUM_RESOLUTION) + (this.D-MINIMUM_RESOLUTION) * q.y) * denom,
bounds);
} else if (Math.abs(denomXZ) >= Math.abs(denomXY) && Math.abs(denomXZ) >= Math.abs(denomYZ)) {
//System.out.println("Y biggest");
// Y is the biggest, so y0 = 0.0
if (Math.abs(denomXZ) < MINIMUM_RESOLUTION_SQUARED) {
//System.err.println(" Denominator is zero: no intersection");
//System.out.println(" Denominator is zero: no intersection");
return;
}
final double denom = 1.0 / denomXZ;
@ -1084,9 +1087,10 @@ public class Plane extends Vector {
(-(this.D-MINIMUM_RESOLUTION) * q.z - this.z * -(q.D-MINIMUM_RESOLUTION)) * denom, 0.0, (this.x * -(q.D-MINIMUM_RESOLUTION) + (this.D-MINIMUM_RESOLUTION) * q.x) * denom,
bounds);
} else {
//System.out.println("Z biggest");
// Z is the biggest, so Z0 = 0.0
if (Math.abs(denomXY) < MINIMUM_RESOLUTION_SQUARED) {
//System.err.println(" Denominator is zero: no intersection");
//System.out.println(" Denominator is zero: no intersection");
return;
}
final double denom = 1.0 / denomXY;
@ -1178,6 +1182,10 @@ public class Plane extends Vector {
if (point2Valid) {
boundsInfo.addPoint(new GeoPoint(point2X, point2Y, point2Z));
}
} else {
// If we can't intersect line with world, then it's outside the world, so
// we have to assume everything is included.
boundsInfo.noBound(planetModel);
}
}

View File

@ -292,6 +292,17 @@ public class XYZBounds implements Bounds {
return this;
}
@Override
public Bounds noBound(final PlanetModel planetModel) {
minX = planetModel.getMinimumXValue();
maxX = planetModel.getMaximumXValue();
minY = planetModel.getMinimumYValue();
maxY = planetModel.getMaximumYValue();
minZ = planetModel.getMinimumZValue();
maxZ = planetModel.getMaximumZValue();
return this;
}
@Override
public String toString() {
return "XYZBounds: [xmin="+minX+" xmax="+maxX+" ymin="+minY+" ymax="+maxY+" zmin="+minZ+" zmax="+maxZ+"]";

View File

@ -372,4 +372,19 @@ public class GeoBBoxTest {
assertTrue(box.isWithin(point)?solid.isWithin(point):true);
}
@Test
public void testFailureCase2() {
//final GeoPoint point = new GeoPoint(-0.7375647084975573, -2.3309121299774915E-10, 0.6746626163258577);
final GeoPoint point = new GeoPoint(-0.737564708579924, -9.032562595264542E-17, 0.6746626165197899);
final GeoBBox box = new GeoRectangle(PlanetModel.WGS84, 0.7988584710911523, 0.25383311815493353, -1.2236144735575564E-12, 7.356011300929654E-49);
final XYZBounds bounds = new XYZBounds();
box.getBounds(bounds);
final XYZSolid solid = XYZSolidFactory.makeXYZSolid(PlanetModel.WGS84, bounds.getMinimumX(), bounds.getMaximumX(), bounds.getMinimumY(), bounds.getMaximumY(), bounds.getMinimumZ(), bounds.getMaximumZ());
//System.out.println("Is within Y value? "+(point.y >= bounds.getMinimumY() && point.y <= bounds.getMaximumY()));
//System.out.println("Shape = "+box+" is within? "+box.isWithin(point));
//System.out.println("XYZBounds = "+bounds+" is within? "+solid.isWithin(point)+" solid="+solid);
assertTrue(box.isWithin(point) == solid.isWithin(point));
}
}