mirror of https://github.com/apache/lucene.git
LUCENE-7241: Get rid of one more allocation during isWithin processing.
This commit is contained in:
parent
49b3eee4c8
commit
1fdc2b9880
|
@ -119,38 +119,33 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
|
||||
@Override
|
||||
public boolean isWithin(final double x, final double y, final double z) {
|
||||
return isWithin(new Vector(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWithin(final Vector thePoint) {
|
||||
// If we're right on top of the point, we know the answer.
|
||||
if (testPoint.isNumericallyIdentical(thePoint)) {
|
||||
if (testPoint.isNumericallyIdentical(x, y, z)) {
|
||||
return testPointInSet;
|
||||
}
|
||||
|
||||
// If we're right on top of any of the test planes, we navigate solely on that plane.
|
||||
if (testPointFixedYPlane.evaluateIsZero(thePoint)) {
|
||||
if (testPointFixedYPlane.evaluateIsZero(x, y, z)) {
|
||||
// Use the XZ plane exclusively.
|
||||
final LinearCrossingEdgeIterator crossingEdgeIterator = new LinearCrossingEdgeIterator(testPointFixedYPlane, testPointFixedYAbovePlane, testPointFixedYBelowPlane, thePoint);
|
||||
final LinearCrossingEdgeIterator crossingEdgeIterator = new LinearCrossingEdgeIterator(testPointFixedYPlane, testPointFixedYAbovePlane, testPointFixedYBelowPlane, x, y, z);
|
||||
// Traverse our way from the test point to the check point. Use the y tree because that's fixed.
|
||||
if (!yTree.traverse(crossingEdgeIterator, testPoint.y)) {
|
||||
// Endpoint is on edge
|
||||
return true;
|
||||
}
|
||||
return ((crossingEdgeIterator.crossingCount & 1) == 0)?testPointInSet:!testPointInSet;
|
||||
} else if (testPointFixedXPlane.evaluateIsZero(thePoint)) {
|
||||
} else if (testPointFixedXPlane.evaluateIsZero(x, y, z)) {
|
||||
// Use the YZ plane exclusively.
|
||||
final LinearCrossingEdgeIterator crossingEdgeIterator = new LinearCrossingEdgeIterator(testPointFixedXPlane, testPointFixedXAbovePlane, testPointFixedXBelowPlane, thePoint);
|
||||
final LinearCrossingEdgeIterator crossingEdgeIterator = new LinearCrossingEdgeIterator(testPointFixedXPlane, testPointFixedXAbovePlane, testPointFixedXBelowPlane, x, y, z);
|
||||
// Traverse our way from the test point to the check point. Use the x tree because that's fixed.
|
||||
if (!xTree.traverse(crossingEdgeIterator, testPoint.x)) {
|
||||
// Endpoint is on edge
|
||||
return true;
|
||||
}
|
||||
return ((crossingEdgeIterator.crossingCount & 1) == 0)?testPointInSet:!testPointInSet;
|
||||
} else if (testPointFixedZPlane.evaluateIsZero(thePoint)) {
|
||||
} else if (testPointFixedZPlane.evaluateIsZero(x, y, z)) {
|
||||
// Use the XY plane exclusively.
|
||||
final LinearCrossingEdgeIterator crossingEdgeIterator = new LinearCrossingEdgeIterator(testPointFixedZPlane, testPointFixedZAbovePlane, testPointFixedZBelowPlane, thePoint);
|
||||
final LinearCrossingEdgeIterator crossingEdgeIterator = new LinearCrossingEdgeIterator(testPointFixedZPlane, testPointFixedZAbovePlane, testPointFixedZBelowPlane, x, y, z);
|
||||
// Traverse our way from the test point to the check point. Use the z tree because that's fixed.
|
||||
if (!zTree.traverse(crossingEdgeIterator, testPoint.z)) {
|
||||
// Endpoint is on edge
|
||||
|
@ -163,9 +158,9 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
// Changing the code below has an enormous impact on the queries per second we see with the benchmark.
|
||||
|
||||
// We need to use two planes to get there. We don't know which two planes will do it but we can figure it out.
|
||||
final Plane travelPlaneFixedX = new Plane(1.0, 0.0, 0.0, -thePoint.x);
|
||||
final Plane travelPlaneFixedY = new Plane(0.0, 1.0, 0.0, -thePoint.y);
|
||||
final Plane travelPlaneFixedZ = new Plane(0.0, 0.0, 1.0, -thePoint.z);
|
||||
final Plane travelPlaneFixedX = new Plane(1.0, 0.0, 0.0, -x);
|
||||
final Plane travelPlaneFixedY = new Plane(0.0, 1.0, 0.0, -y);
|
||||
final Plane travelPlaneFixedZ = new Plane(0.0, 0.0, 1.0, -z);
|
||||
|
||||
// Find the intersection points for each one of these and the complementary test point planes.
|
||||
final GeoPoint[] XIntersectionsY = travelPlaneFixedX.findIntersections(planetModel, testPointFixedYPlane);
|
||||
|
@ -193,15 +188,15 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
//final double newDistance = p.arcDistance(testPoint) + p.arcDistance(thePoint);
|
||||
final double tpDelta1 = testPoint.x - p.x;
|
||||
final double tpDelta2 = testPoint.z - p.z;
|
||||
final double cpDelta1 = thePoint.y - p.y;
|
||||
final double cpDelta2 = thePoint.z - p.z;
|
||||
final double cpDelta1 = y - p.y;
|
||||
final double cpDelta2 = z - p.z;
|
||||
final double newDistance = tpDelta1 * tpDelta1 + tpDelta2 * tpDelta2 + cpDelta1 * cpDelta1 + cpDelta2 * cpDelta2;
|
||||
//final double newDistance = (testPoint.x - p.x) * (testPoint.x - p.x) + (testPoint.z - p.z) * (testPoint.z - p.z) + (thePoint.y - p.y) * (thePoint.y - p.y) + (thePoint.z - p.z) * (thePoint.z - p.z);
|
||||
//final double newDistance = Math.abs(testPoint.x - p.x) + Math.abs(thePoint.y - p.y);
|
||||
if (newDistance < bestDistance) {
|
||||
bestDistance = newDistance;
|
||||
firstLegValue = testPoint.y;
|
||||
secondLegValue = thePoint.x;
|
||||
secondLegValue = x;
|
||||
firstLegPlane = testPointFixedYPlane;
|
||||
firstLegAbovePlane = testPointFixedYAbovePlane;
|
||||
firstLegBelowPlane = testPointFixedYBelowPlane;
|
||||
|
@ -216,15 +211,15 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
//final double newDistance = p.arcDistance(testPoint) + p.arcDistance(thePoint);
|
||||
final double tpDelta1 = testPoint.x - p.x;
|
||||
final double tpDelta2 = testPoint.y - p.y;
|
||||
final double cpDelta1 = thePoint.y - p.y;
|
||||
final double cpDelta2 = thePoint.z - p.z;
|
||||
final double cpDelta1 = y - p.y;
|
||||
final double cpDelta2 = z - p.z;
|
||||
final double newDistance = tpDelta1 * tpDelta1 + tpDelta2 * tpDelta2 + cpDelta1 * cpDelta1 + cpDelta2 * cpDelta2;
|
||||
//final double newDistance = (testPoint.x - p.x) * (testPoint.x - p.x) + (testPoint.y - p.y) * (testPoint.y - p.y) + (thePoint.y - p.y) * (thePoint.y - p.y) + (thePoint.z - p.z) * (thePoint.z - p.z);
|
||||
//final double newDistance = Math.abs(testPoint.x - p.x) + Math.abs(thePoint.z - p.z);
|
||||
if (newDistance < bestDistance) {
|
||||
bestDistance = newDistance;
|
||||
firstLegValue = testPoint.z;
|
||||
secondLegValue = thePoint.x;
|
||||
secondLegValue = x;
|
||||
firstLegPlane = testPointFixedZPlane;
|
||||
firstLegAbovePlane = testPointFixedZAbovePlane;
|
||||
firstLegBelowPlane = testPointFixedZBelowPlane;
|
||||
|
@ -239,15 +234,15 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
//final double newDistance = p.arcDistance(testPoint) + p.arcDistance(thePoint);
|
||||
final double tpDelta1 = testPoint.y - p.y;
|
||||
final double tpDelta2 = testPoint.z - p.z;
|
||||
final double cpDelta1 = thePoint.x - p.x;
|
||||
final double cpDelta2 = thePoint.z - p.z;
|
||||
final double cpDelta1 = x - p.x;
|
||||
final double cpDelta2 = z - p.z;
|
||||
final double newDistance = tpDelta1 * tpDelta1 + tpDelta2 * tpDelta2 + cpDelta1 * cpDelta1 + cpDelta2 * cpDelta2;
|
||||
//final double newDistance = (testPoint.y - p.y) * (testPoint.y - p.y) + (testPoint.z - p.z) * (testPoint.z - p.z) + (thePoint.x - p.x) * (thePoint.x - p.x) + (thePoint.z - p.z) * (thePoint.z - p.z);
|
||||
//final double newDistance = Math.abs(testPoint.y - p.y) + Math.abs(thePoint.x - p.x);
|
||||
if (newDistance < bestDistance) {
|
||||
bestDistance = newDistance;
|
||||
firstLegValue = testPoint.x;
|
||||
secondLegValue = thePoint.y;
|
||||
secondLegValue = y;
|
||||
firstLegPlane = testPointFixedXPlane;
|
||||
firstLegAbovePlane = testPointFixedXAbovePlane;
|
||||
firstLegBelowPlane = testPointFixedXBelowPlane;
|
||||
|
@ -262,15 +257,15 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
//final double newDistance = p.arcDistance(testPoint) + p.arcDistance(thePoint);
|
||||
final double tpDelta1 = testPoint.x - p.x;
|
||||
final double tpDelta2 = testPoint.y - p.y;
|
||||
final double cpDelta1 = thePoint.x - p.x;
|
||||
final double cpDelta2 = thePoint.z - p.z;
|
||||
final double cpDelta1 = x - p.x;
|
||||
final double cpDelta2 = z - p.z;
|
||||
final double newDistance = tpDelta1 * tpDelta1 + tpDelta2 * tpDelta2 + cpDelta1 * cpDelta1 + cpDelta2 * cpDelta2;
|
||||
//final double newDistance = (testPoint.x - p.x) * (testPoint.x - p.x) + (testPoint.y - p.y) * (testPoint.y - p.y) + (thePoint.x - p.x) * (thePoint.x - p.x) + (thePoint.z - p.z) * (thePoint.z - p.z);
|
||||
//final double newDistance = Math.abs(testPoint.y - p.y) + Math.abs(thePoint.z - p.z);
|
||||
if (newDistance < bestDistance) {
|
||||
bestDistance = newDistance;
|
||||
firstLegValue = testPoint.z;
|
||||
secondLegValue = thePoint.y;
|
||||
secondLegValue = y;
|
||||
firstLegPlane = testPointFixedZPlane;
|
||||
firstLegAbovePlane = testPointFixedZAbovePlane;
|
||||
firstLegBelowPlane = testPointFixedZBelowPlane;
|
||||
|
@ -285,15 +280,15 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
//final double newDistance = p.arcDistance(testPoint) + p.arcDistance(thePoint);
|
||||
final double tpDelta1 = testPoint.y - p.y;
|
||||
final double tpDelta2 = testPoint.z - p.z;
|
||||
final double cpDelta1 = thePoint.y - p.y;
|
||||
final double cpDelta2 = thePoint.x - p.x;
|
||||
final double cpDelta1 = y - p.y;
|
||||
final double cpDelta2 = x - p.x;
|
||||
final double newDistance = tpDelta1 * tpDelta1 + tpDelta2 * tpDelta2 + cpDelta1 * cpDelta1 + cpDelta2 * cpDelta2;
|
||||
//final double newDistance = (testPoint.y - p.y) * (testPoint.y - p.y) + (testPoint.z - p.z) * (testPoint.z - p.z) + (thePoint.y - p.y) * (thePoint.y - p.y) + (thePoint.x - p.x) * (thePoint.x - p.x);
|
||||
//final double newDistance = Math.abs(testPoint.z - p.z) + Math.abs(thePoint.x - p.x);
|
||||
if (newDistance < bestDistance) {
|
||||
bestDistance = newDistance;
|
||||
firstLegValue = testPoint.x;
|
||||
secondLegValue = thePoint.z;
|
||||
secondLegValue = z;
|
||||
firstLegPlane = testPointFixedXPlane;
|
||||
firstLegAbovePlane = testPointFixedXAbovePlane;
|
||||
firstLegBelowPlane = testPointFixedXBelowPlane;
|
||||
|
@ -308,15 +303,15 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
//final double newDistance = p.arcDistance(testPoint) + p.arcDistance(thePoint);
|
||||
final double tpDelta1 = testPoint.x - p.x;
|
||||
final double tpDelta2 = testPoint.z - p.z;
|
||||
final double cpDelta1 = thePoint.y - p.y;
|
||||
final double cpDelta2 = thePoint.x - p.x;
|
||||
final double cpDelta1 = y - p.y;
|
||||
final double cpDelta2 = x - p.x;
|
||||
final double newDistance = tpDelta1 * tpDelta1 + tpDelta2 * tpDelta2 + cpDelta1 * cpDelta1 + cpDelta2 * cpDelta2;
|
||||
//final double newDistance = (testPoint.x - p.x) * (testPoint.x - p.x) + (testPoint.z - p.z) * (testPoint.z - p.z) + (thePoint.y - p.y) * (thePoint.y - p.y) + (thePoint.x - p.x) * (thePoint.x - p.x);
|
||||
//final double newDistance = Math.abs(testPoint.z - p.z) + Math.abs(thePoint.y - p.y);
|
||||
if (newDistance < bestDistance) {
|
||||
bestDistance = newDistance;
|
||||
firstLegValue = testPoint.y;
|
||||
secondLegValue = thePoint.z;
|
||||
secondLegValue = z;
|
||||
firstLegPlane = testPointFixedYPlane;
|
||||
firstLegAbovePlane = testPointFixedYAbovePlane;
|
||||
firstLegBelowPlane = testPointFixedYBelowPlane;
|
||||
|
@ -330,7 +325,7 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
assert bestDistance > 0.0 : "Best distance should not be zero unless on single plane";
|
||||
assert bestDistance < Double.MAX_VALUE : "Couldn't find an intersection point of any kind";
|
||||
|
||||
final DualCrossingEdgeIterator edgeIterator = new DualCrossingEdgeIterator(firstLegPlane, firstLegAbovePlane, firstLegBelowPlane, secondLegPlane, thePoint, intersectionPoint);
|
||||
final DualCrossingEdgeIterator edgeIterator = new DualCrossingEdgeIterator(firstLegPlane, firstLegAbovePlane, firstLegBelowPlane, secondLegPlane, x, y, z, intersectionPoint);
|
||||
if (!firstLegTree.traverse(edgeIterator, firstLegValue)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -708,23 +703,27 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
private final Plane belowPlane;
|
||||
private final Membership bound1;
|
||||
private final Membership bound2;
|
||||
private final Vector thePoint;
|
||||
private final double thePointX;
|
||||
private final double thePointY;
|
||||
private final double thePointZ;
|
||||
|
||||
public int crossingCount = 0;
|
||||
|
||||
public LinearCrossingEdgeIterator(final Plane plane, final Plane abovePlane, final Plane belowPlane, final Vector thePoint) {
|
||||
public LinearCrossingEdgeIterator(final Plane plane, final Plane abovePlane, final Plane belowPlane, final double thePointX, final double thePointY, final double thePointZ) {
|
||||
this.plane = plane;
|
||||
this.abovePlane = abovePlane;
|
||||
this.belowPlane = belowPlane;
|
||||
this.bound1 = new SidedPlane(thePoint, plane, testPoint);
|
||||
this.bound2 = new SidedPlane(testPoint, plane, thePoint);
|
||||
this.thePoint = thePoint;
|
||||
this.bound1 = new SidedPlane(thePointX, thePointY, thePointZ, plane, testPoint);
|
||||
this.bound2 = new SidedPlane(testPoint, plane, thePointX, thePointY, thePointZ);
|
||||
this.thePointX = thePointX;
|
||||
this.thePointY = thePointY;
|
||||
this.thePointZ = thePointZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(final Edge edge) {
|
||||
// Early exit if the point is on the edge.
|
||||
if (thePoint != null && edge.plane.evaluateIsZero(thePoint) && edge.startPlane.isWithin(thePoint) && edge.endPlane.isWithin(thePoint)) {
|
||||
if (edge.plane.evaluateIsZero(thePointX, thePointY, thePointZ) && edge.startPlane.isWithin(thePointX, thePointY, thePointZ) && edge.endPlane.isWithin(thePointX, thePointY, thePointZ)) {
|
||||
return false;
|
||||
}
|
||||
final GeoPoint[] crossingPoints = plane.findCrossings(planetModel, edge.plane, bound1, bound2, edge.startPlane, edge.endPlane);
|
||||
|
@ -864,7 +863,9 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
private final Plane testPointAbovePlane;
|
||||
private final Plane testPointBelowPlane;
|
||||
private final Plane travelPlane;
|
||||
private final Vector thePoint;
|
||||
private final double thePointX;
|
||||
private final double thePointY;
|
||||
private final double thePointZ;
|
||||
|
||||
private final GeoPoint intersectionPoint;
|
||||
|
||||
|
@ -888,12 +889,14 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
public int crossingCount = 0;
|
||||
|
||||
public DualCrossingEdgeIterator(final Plane testPointPlane, final Plane testPointAbovePlane, final Plane testPointBelowPlane,
|
||||
final Plane travelPlane, final Vector thePoint, final GeoPoint intersectionPoint) {
|
||||
final Plane travelPlane, final double thePointX, final double thePointY, final double thePointZ, final GeoPoint intersectionPoint) {
|
||||
this.testPointPlane = testPointPlane;
|
||||
this.testPointAbovePlane = testPointAbovePlane;
|
||||
this.testPointBelowPlane = testPointBelowPlane;
|
||||
this.travelPlane = travelPlane;
|
||||
this.thePoint = thePoint;
|
||||
this.thePointX = thePointX;
|
||||
this.thePointY = thePointY;
|
||||
this.thePointZ = thePointZ;
|
||||
this.intersectionPoint = intersectionPoint;
|
||||
|
||||
//System.err.println("Intersection point = "+intersectionPoint);
|
||||
|
@ -902,12 +905,12 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
assert testPointPlane.evaluateIsZero(intersectionPoint) : "intersection point must be on test point plane";
|
||||
|
||||
assert !testPoint.isNumericallyIdentical(intersectionPoint) : "test point is the same as intersection point";
|
||||
assert !thePoint.isNumericallyIdentical(intersectionPoint) : "check point is same is intersection point";
|
||||
assert !intersectionPoint.isNumericallyIdentical(thePointX, thePointY, thePointZ) : "check point is same is intersection point";
|
||||
|
||||
this.testPointCutoffPlane = new SidedPlane(intersectionPoint, testPointPlane, testPoint);
|
||||
this.checkPointCutoffPlane = new SidedPlane(intersectionPoint, travelPlane, thePoint);
|
||||
this.checkPointCutoffPlane = new SidedPlane(intersectionPoint, travelPlane, thePointX, thePointY, thePointZ);
|
||||
this.testPointOtherCutoffPlane = new SidedPlane(testPoint, testPointPlane, intersectionPoint);
|
||||
this.checkPointOtherCutoffPlane = new SidedPlane(thePoint, travelPlane, intersectionPoint);
|
||||
this.checkPointOtherCutoffPlane = new SidedPlane(thePointX, thePointY, thePointZ, travelPlane, intersectionPoint);
|
||||
|
||||
// Sanity check
|
||||
assert testPointCutoffPlane.isWithin(intersectionPoint) : "intersection must be within testPointCutoffPlane";
|
||||
|
@ -922,7 +925,7 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
// Convert travel plane to a sided plane
|
||||
final Membership intersectionBound1 = new SidedPlane(testPoint, travelPlane, travelPlane.D);
|
||||
// Convert testPoint plane to a sided plane
|
||||
final Membership intersectionBound2 = new SidedPlane(thePoint, testPointPlane, testPointPlane.D);
|
||||
final Membership intersectionBound2 = new SidedPlane(thePointX, thePointY, thePointZ, testPointPlane, testPointPlane.D);
|
||||
|
||||
assert intersectionBound1.isWithin(intersectionPoint) : "intersection must be within intersectionBound1";
|
||||
assert intersectionBound2.isWithin(intersectionPoint) : "intersection must be within intersectionBound2";
|
||||
|
@ -966,7 +969,7 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
testPointOutsidePlane = testPointBelowPlane;
|
||||
}
|
||||
|
||||
insideTravelCutoffPlane = new SidedPlane(thePoint, testPointInsidePlane, testPointInsidePlane.D);
|
||||
insideTravelCutoffPlane = new SidedPlane(thePointX, thePointY, thePointZ, testPointInsidePlane, testPointInsidePlane.D);
|
||||
insideTestPointCutoffPlane = new SidedPlane(testPoint, travelInsidePlane, travelInsidePlane.D);
|
||||
computedInsideOutside = true;
|
||||
}
|
||||
|
@ -980,7 +983,7 @@ class GeoComplexPolygon extends GeoBasePolygon {
|
|||
public boolean matches(final Edge edge) {
|
||||
//System.err.println("Processing edge "+edge+", startpoint="+edge.startPoint+" endpoint="+edge.endPoint);
|
||||
// Early exit if the point is on the edge.
|
||||
if (thePoint != null && edge.plane.evaluateIsZero(thePoint) && edge.startPlane.isWithin(thePoint) && edge.endPlane.isWithin(thePoint)) {
|
||||
if (edge.plane.evaluateIsZero(thePointX, thePointY, thePointZ) && edge.startPlane.isWithin(thePointX, thePointY, thePointZ) && edge.endPlane.isWithin(thePointX, thePointY, thePointZ)) {
|
||||
//System.err.println(" Check point is on edge: isWithin = true");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,19 @@ public class Plane extends Vector {
|
|||
this.D = D;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a plane through two points and origin.
|
||||
*
|
||||
* @param A is the first point (origin based).
|
||||
* @param BX is the second point X (origin based).
|
||||
* @param BY is the second point Y (origin based).
|
||||
* @param BZ is the second point Z (origin based).
|
||||
*/
|
||||
public Plane(final Vector A, final double BX, final double BY, final double BZ) {
|
||||
super(A, BX, BY, BZ);
|
||||
D = 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a plane through two points and origin.
|
||||
*
|
||||
|
|
|
@ -36,6 +36,23 @@ public class SidedPlane extends Plane implements Membership {
|
|||
this.sigNum = -sidedPlane.sigNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a sided plane from a pair of vectors describing points, and including
|
||||
* origin, plus a point p which describes the side.
|
||||
*
|
||||
* @param pX point X to evaluate
|
||||
* @param pY point Y to evaluate
|
||||
* @param pZ point Z to evaluate
|
||||
* @param A is the first in-plane point
|
||||
* @param B is the second in-plane point
|
||||
*/
|
||||
public SidedPlane(final double pX, final double pY, final double pZ, final Vector A, final Vector B) {
|
||||
super(A, B);
|
||||
sigNum = Math.signum(evaluate(pX, pY, pZ));
|
||||
if (sigNum == 0.0)
|
||||
throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a sided plane from a pair of vectors describing points, and including
|
||||
* origin, plus a point p which describes the side.
|
||||
|
@ -51,6 +68,23 @@ public class SidedPlane extends Plane implements Membership {
|
|||
throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a sided plane from a pair of vectors describing points, and including
|
||||
* origin, plus a point p which describes the side.
|
||||
*
|
||||
* @param p point to evaluate
|
||||
* @param A is the first in-plane point
|
||||
* @param BX is the X value of the second in-plane point
|
||||
* @param BY is the Y value of the second in-plane point
|
||||
* @param BZ is the Z value of the second in-plane point
|
||||
*/
|
||||
public SidedPlane(final Vector p, final Vector A, final double BX, final double BY, final double BZ) {
|
||||
super(A, BX, BY, BZ);
|
||||
sigNum = Math.signum(evaluate(p));
|
||||
if (sigNum == 0.0)
|
||||
throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a sided plane from a pair of vectors describing points, and including
|
||||
* origin, plus a point p which describes the side.
|
||||
|
|
|
@ -56,6 +56,34 @@ public class Vector {
|
|||
this.z = z;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 A is the first vector
|
||||
* @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 Vector A, final double BX, final double BY, final double BZ) {
|
||||
// x = u2v3 - u3v2
|
||||
// y = u3v1 - u1v3
|
||||
// z = u1v2 - u2v1
|
||||
final double thisX = A.y * BZ - A.z * BY;
|
||||
final double thisY = A.z * BX - A.x * BZ;
|
||||
final double thisZ = A.x * BY - A.y * BX;
|
||||
final double magnitude = magnitude(thisX, thisY, thisZ);
|
||||
if (Math.abs(magnitude) < MINIMUM_RESOLUTION) {
|
||||
throw new IllegalArgumentException("Degenerate/parallel vector constructed");
|
||||
}
|
||||
final double inverseMagnitude = 1.0 / magnitude;
|
||||
this.x = thisX * inverseMagnitude;
|
||||
this.y = thisY * inverseMagnitude;
|
||||
this.z = thisZ * inverseMagnitude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a vector that is perpendicular to
|
||||
* two other (non-zero) vectors. If the vectors are parallel,
|
||||
|
@ -328,6 +356,20 @@ public class Vector {
|
|||
return magnitude(x,y,z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute whether two vectors are numerically identical.
|
||||
* @param otherX is the other vector X.
|
||||
* @param otherY is the other vector Y.
|
||||
* @param otherZ is the other vector Z.
|
||||
* @return true if they are numerically identical.
|
||||
*/
|
||||
public boolean isNumericallyIdentical(final double otherX, final double otherY, final double otherZ) {
|
||||
final double thisX = y * otherZ - z * otherY;
|
||||
final double thisY = z * otherX - x * otherZ;
|
||||
final double thisZ = x * otherY - y * otherX;
|
||||
return thisX * thisX + thisY * thisY + thisZ * thisZ < MINIMUM_RESOLUTION_SQUARED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute whether two vectors are numerically identical.
|
||||
* @param other is the other vector.
|
||||
|
|
Loading…
Reference in New Issue