LUCENE-8171: Refactor vector constructor to support later changes, and add an ignored test for a precision issue.

This commit is contained in:
Karl Wright 2018-02-13 09:53:04 -05:00
parent 277097cd24
commit 4f351fd21b
3 changed files with 85 additions and 14 deletions

View File

@ -177,14 +177,39 @@ public class SidedPlane extends Plane implements Membership {
*/ */
public static SidedPlane constructNormalizedThreePointSidedPlane(final Vector insidePoint, public static SidedPlane constructNormalizedThreePointSidedPlane(final Vector insidePoint,
final Vector point1, final Vector point2, final Vector point3) { final Vector point1, final Vector point2, final Vector point3) {
try { SidedPlane rval = null;
final Vector planeNormal = new Vector(
new Vector(point1.x - point2.x, point1.y - point2.y, point1.z - point2.z), if (rval == null) {
new Vector(point2.x - point3.x, point2.y - point3.y, point2.z - point3.z)); try {
return new SidedPlane(insidePoint, planeNormal, -planeNormal.dotProduct(point2)); final Vector planeNormal = new Vector(
} catch (IllegalArgumentException e) { point1.x - point2.x, point1.y - point2.y, point1.z - point2.z,
return null; point2.x - point3.x, point2.y - point3.y, point2.z - point3.z);
rval = new SidedPlane(insidePoint, planeNormal, -planeNormal.dotProduct(point2));
} catch (IllegalArgumentException e) {
}
} }
if (rval == null) {
try {
final Vector planeNormal = new Vector(
point1.x - point3.x, point1.y - point3.y, point1.z - point3.z,
point3.x - point2.x, point3.y - point2.y, point3.z - point2.z);
rval = new SidedPlane(insidePoint, planeNormal, -planeNormal.dotProduct(point3));
} catch (IllegalArgumentException e) {
}
}
if (rval == null) {
try {
final Vector planeNormal = new Vector(
point3.x - point1.x, point3.y - point1.y, point3.z - point1.z,
point1.x - point2.x, point1.y - point2.y, point1.z - point2.z);
rval = new SidedPlane(insidePoint, planeNormal, -planeNormal.dotProduct(point1));
} catch (IllegalArgumentException e) {
}
}
return rval;
} }
@Override @Override

View File

@ -72,6 +72,24 @@ public class Vector {
* @param BZ is the Z value of the second * @param BZ is the Z value of the second
*/ */
public Vector(final Vector A, final double BX, final double BY, final double BZ) { public Vector(final Vector A, final double BX, final double BY, final double BZ) {
// We're really looking at two vectors and computing a perpendicular one from that.
this(A.x, A.y, A.z, BX, BY, BZ);
}
/**
* Construct a vector that is perpendicular to
* two other (non-zero) vectors. If the vectors are parallel,
* IllegalArgumentException will be thrown.
* Produces a normalized final vector.
*
* @param AX is the X value of the first
* @param AY is the Y value of the first
* @param AZ is the Z value of the first
* @param BX is the X value of the second
* @param BY is the Y value of the second
* @param BZ is the Z value of the second
*/
public Vector(final double AX, final double AY, final double AZ, final double BX, final double BY, final double BZ) {
// We're really looking at two vectors and computing a perpendicular one from that. // We're really looking at two vectors and computing a perpendicular one from that.
// We can think of this as having three points -- the origin, and two points that aren't the origin. // We can think of this as having three points -- the origin, and two points that aren't the origin.
// Normally, we can compute the perpendicular vector this way: // Normally, we can compute the perpendicular vector this way:
@ -83,9 +101,9 @@ public class Vector {
// Gram-Schmidt process: https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process // Gram-Schmidt process: https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process
// Compute the naive perpendicular // Compute the naive perpendicular
final double thisX = A.y * BZ - A.z * BY; final double thisX = AY * BZ - AZ * BY;
final double thisY = A.z * BX - A.x * BZ; final double thisY = AZ * BX - AX * BZ;
final double thisZ = A.x * BY - A.y * BX; final double thisZ = AX * BY - AY * BX;
final double magnitude = magnitude(thisX, thisY, thisZ); final double magnitude = magnitude(thisX, thisY, thisZ);
if (magnitude < MINIMUM_RESOLUTION) { if (magnitude < MINIMUM_RESOLUTION) {
@ -103,7 +121,7 @@ public class Vector {
// we need to adjust // we need to adjust
int i = 0; int i = 0;
while (true) { while (true) {
final double currentDotProdA = A.x * normalizeX + A.y * normalizeY + A.z * normalizeZ; final double currentDotProdA = AX * normalizeX + AY * normalizeY + AZ * normalizeZ;
final double currentDotProdB = BX * normalizeX + BY * normalizeY + BZ * normalizeZ; final double currentDotProdB = BX * normalizeX + BY * normalizeY + BZ * normalizeZ;
if (Math.abs(currentDotProdA) < MINIMUM_RESOLUTION && Math.abs(currentDotProdB) < MINIMUM_RESOLUTION) { if (Math.abs(currentDotProdA) < MINIMUM_RESOLUTION && Math.abs(currentDotProdB) < MINIMUM_RESOLUTION) {
break; break;
@ -114,9 +132,9 @@ public class Vector {
final double currentVectorZ; final double currentVectorZ;
final double currentDotProd; final double currentDotProd;
if (Math.abs(currentDotProdA) > Math.abs(currentDotProdB)) { if (Math.abs(currentDotProdA) > Math.abs(currentDotProdB)) {
currentVectorX = A.x; currentVectorX = AX;
currentVectorY = A.y; currentVectorY = AY;
currentVectorZ = A.z; currentVectorZ = AZ;
currentDotProd = currentDotProdA; currentDotProd = currentDotProdA;
} else { } else {
currentVectorX = BX; currentVectorX = BX;

View File

@ -22,6 +22,7 @@ import java.util.List;
import com.carrotsearch.randomizedtesting.annotations.Repeat; import com.carrotsearch.randomizedtesting.annotations.Repeat;
import org.junit.Test; import org.junit.Test;
import org.junit.Ignore;
/** /**
* Random test for planes. * Random test for planes.
@ -50,6 +51,33 @@ public class RandomPlaneTest extends RandomGeo3dShapeGenerator {
} }
} }
} }
@Ignore
@Test
@Repeat(iterations = 10)
public void testPlaneThreePointsAccuracy() {
PlanetModel planetModel = randomPlanetModel();
for (int i= 0; i < 1000; i++) {
GeoPoint point1 = randomGeoPoint(planetModel);
double dist = random().nextDouble() * Math.PI - Vector.MINIMUM_ANGULAR_RESOLUTION;
double bearing = random().nextDouble() * 2 * Math.PI;
GeoPoint point2 = planetModel.surfacePointOnBearing(point1, dist, bearing );
dist = random().nextDouble() * Vector.MINIMUM_ANGULAR_RESOLUTION + Vector.MINIMUM_ANGULAR_RESOLUTION;
bearing = random().nextDouble() * 2 * Math.PI;
GeoPoint point3 = planetModel.surfacePointOnBearing(point1, dist, bearing );
GeoPoint check = randomGeoPoint(planetModel);
SidedPlane plane = SidedPlane.constructNormalizedThreePointSidedPlane(check, point1, point2, point3);
String msg = planetModel + " point 1: " + point1 + ", point 2: " + point2 + ", point 3: " + point3 + " , check: " + check;
if (plane == null) {
fail(msg);
}
assertTrue(plane.evaluate(check) + " " + msg, plane.isWithin(check));
assertTrue(plane.evaluate(point1) + " " +msg, plane.isWithin(point3));
assertTrue(plane.evaluate(point2) + " " +msg, plane.isWithin(point2));
assertTrue(plane.evaluate(point3) + " " +msg, plane.isWithin(point1));
}
}
@Test @Test