mirror of https://github.com/apache/lucene.git
LUCENE-7642: Take the slightly more cautious approach of introducing a plane method for functional identicality.
This commit is contained in:
parent
dc9c60322a
commit
b4a83fffbd
|
@ -1239,7 +1239,7 @@ public class GeoPolygonFactory {
|
|||
final Edge newLastEdge = edgeBuffer.getNext(lastEdge);
|
||||
// Planes that are almost identical cannot be properly handled by the standard polygon logic. Detect this case and, if found,
|
||||
// give up on the tiling -- we'll need to create a large poly instead.
|
||||
if (lastEdge.plane.isNumericallyIdentical(newLastEdge.plane) /*isNearlyIdentical(lastEdge.plane, newLastEdge.plane) */) {
|
||||
if (lastEdge.plane.isFunctionallyIdentical(newLastEdge.plane)) {
|
||||
throw new TileException("Two adjacent edge planes are effectively parallel despite filtering; give up on tiling");
|
||||
}
|
||||
if (Plane.arePointsCoplanar(lastEdge.startPoint, lastEdge.endPoint, newLastEdge.endPoint)) {
|
||||
|
|
|
@ -2344,6 +2344,43 @@ public class Plane extends Vector {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this plane and the other plane are functionally identical within the margin of error.
|
||||
* Functionally identical means that the planes are so close to parallel that many aspects of planar math,
|
||||
* like intersections, no longer have answers to within the required precision.
|
||||
* @param p is the plane to compare against.
|
||||
* @return true if the planes are functionally identical.
|
||||
*/
|
||||
public boolean isFunctionallyIdentical(final Plane p) {
|
||||
// We can get the correlation by just doing a parallel plane check. That's basically finding
|
||||
// out if the magnitude of the cross-product is "zero".
|
||||
final double cross1 = this.y * p.z - this.z * p.y;
|
||||
final double cross2 = this.z * p.x - this.x * p.z;
|
||||
final double cross3 = this.x * p.y - this.y * p.x;
|
||||
//System.out.println("cross product magnitude = "+(cross1 * cross1 + cross2 * cross2 + cross3 * cross3));
|
||||
// Should be MINIMUM_RESOLUTION_SQUARED, but that gives us planes that are *almost* parallel, and those are problematic too,
|
||||
// so we have a tighter constraint on parallelism in this method.
|
||||
if (cross1 * cross1 + cross2 * cross2 + cross3 * cross3 >= MINIMUM_RESOLUTION) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now, see whether the parallel planes are in fact on top of one another.
|
||||
// The math:
|
||||
// We need a single point that fulfills:
|
||||
// Ax + By + Cz + D = 0
|
||||
// Pick:
|
||||
// x0 = -(A * D) / (A^2 + B^2 + C^2)
|
||||
// y0 = -(B * D) / (A^2 + B^2 + C^2)
|
||||
// z0 = -(C * D) / (A^2 + B^2 + C^2)
|
||||
// Check:
|
||||
// A (x0) + B (y0) + C (z0) + D =? 0
|
||||
// A (-(A * D) / (A^2 + B^2 + C^2)) + B (-(B * D) / (A^2 + B^2 + C^2)) + C (-(C * D) / (A^2 + B^2 + C^2)) + D ?= 0
|
||||
// -D [ A^2 / (A^2 + B^2 + C^2) + B^2 / (A^2 + B^2 + C^2) + C^2 / (A^2 + B^2 + C^2)] + D ?= 0
|
||||
// Yes.
|
||||
final double denom = 1.0 / (p.x * p.x + p.y * p.y + p.z * p.z);
|
||||
return evaluateIsZero(-p.x * p.D * denom, -p.y * p.D * denom, -p.z * p.D * denom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this plane and the other plane are identical within the margin of error.
|
||||
* @param p is the plane to compare against.
|
||||
|
@ -2356,8 +2393,7 @@ public class Plane extends Vector {
|
|||
final double cross2 = this.z * p.x - this.x * p.z;
|
||||
final double cross3 = this.x * p.y - this.y * p.x;
|
||||
//System.out.println("cross product magnitude = "+(cross1 * cross1 + cross2 * cross2 + cross3 * cross3));
|
||||
// Technically should be MINIMUM_RESOLUTION_SQUARED, but that gives us planes that are *almost* parallel, and those are problematic too
|
||||
if (cross1 * cross1 + cross2 * cross2 + cross3 * cross3 >= MINIMUM_RESOLUTION) {
|
||||
if (cross1 * cross1 + cross2 * cross2 + cross3 * cross3 >= MINIMUM_RESOLUTION_SQUARED) {
|
||||
return false;
|
||||
}
|
||||
/* Old method
|
||||
|
|
Loading…
Reference in New Issue