LUCENE-8696: Refactor, in preparation for creating a new SegmentEndpoint implementation to fix the problem.

This commit is contained in:
Karl Wright 2019-02-26 08:43:48 -05:00
parent 8c34da8a62
commit 149469ddbc
2 changed files with 358 additions and 162 deletions

View File

@ -148,7 +148,7 @@ class GeoStandardPath extends GeoBasePath {
// Construct normal plane
final Plane normalPlane = Plane.constructNormalizedZPlane(upperPoint, lowerPoint, point);
final SegmentEndpoint onlyEndpoint = new SegmentEndpoint(point, normalPlane, upperPoint, lowerPoint);
final CircleSegmentEndpoint onlyEndpoint = new CircleSegmentEndpoint(point, normalPlane, upperPoint, lowerPoint);
endPoints.add(onlyEndpoint);
this.edgePoints = new GeoPoint[]{onlyEndpoint.circlePlane.getSampleIntersectionPoint(planetModel, normalPlane)};
return;
@ -160,7 +160,7 @@ class GeoStandardPath extends GeoBasePath {
if (i == 0) {
// Starting endpoint
final SegmentEndpoint startEndpoint = new SegmentEndpoint(currentSegment.start,
final SegmentEndpoint startEndpoint = new CutoffSingleCircleSegmentEndpoint(currentSegment.start,
currentSegment.startCutoffPlane, currentSegment.ULHC, currentSegment.LLHC);
endPoints.add(startEndpoint);
this.edgePoints = new GeoPoint[]{currentSegment.ULHC};
@ -178,12 +178,12 @@ class GeoStandardPath extends GeoBasePath {
if (candidate1 == null && candidate2 == null && candidate3 == null && candidate4 == null) {
// The planes are identical. We wouldn't need a circle at all except for the possibility of
// backing up, which is hard to detect here.
final SegmentEndpoint midEndpoint = new SegmentEndpoint(currentSegment.start,
final SegmentEndpoint midEndpoint = new CutoffSingleCircleSegmentEndpoint(currentSegment.start,
prevSegment.endCutoffPlane, currentSegment.startCutoffPlane, currentSegment.ULHC, currentSegment.LLHC);
//don't need a circle at all. Special constructor...
endPoints.add(midEndpoint);
} else {
endPoints.add(new SegmentEndpoint(currentSegment.start,
endPoints.add(new CutoffDualCircleSegmentEndpoint(currentSegment.start,
prevSegment.endCutoffPlane, currentSegment.startCutoffPlane,
prevSegment.URHC, prevSegment.LRHC,
currentSegment.ULHC, currentSegment.LLHC,
@ -192,7 +192,7 @@ class GeoStandardPath extends GeoBasePath {
}
// Do final endpoint
final PathSegment lastSegment = segments.get(segments.size()-1);
endPoints.add(new SegmentEndpoint(lastSegment.end,
endPoints.add(new CutoffSingleCircleSegmentEndpoint(lastSegment.end,
lastSegment.endCutoffPlane, lastSegment.URHC, lastSegment.LRHC));
}
@ -458,7 +458,8 @@ class GeoStandardPath extends GeoBasePath {
}
/**
* This is precalculated data for segment endpoint.
* Internal interface describing segment endpoint implementations.
* There are several different such implementations, each corresponding to a different geometric conformation.
* Note well: This is not necessarily a circle. There are four cases:
* (1) The path consists of a single endpoint. In this case, we build a simple circle with the proper cutoff offset.
* (2) This is the end of a path. The circle plane must be constructed to go through two supplied points and be perpendicular to a connecting plane.
@ -467,43 +468,258 @@ class GeoStandardPath extends GeoBasePath {
* we generate no circle at all. If there is one intersection only, then we generate a plane that includes that intersection, as well as the remaining
* cutoff plane/edge plane points.
*/
private static class SegmentEndpoint {
/** The center point of the endpoint */
public final GeoPoint point;
/** A plane describing the circle */
public final SidedPlane circlePlane;
/** Pertinent cutoff planes from adjoining segments */
public final Membership[] cutoffPlanes;
/** Notable points for this segment endpoint */
public final GeoPoint[] notablePoints;
/** No notable points from the circle itself */
public final static GeoPoint[] circlePoints = new GeoPoint[0];
/** Null membership */
public final static Membership[] NO_MEMBERSHIP = new Membership[0];
private interface SegmentEndpoint {
/** Base case. Does nothing at all.
/** Check if point is within this endpoint.
*@param point is the point.
*@return true of within.
*/
public SegmentEndpoint(final GeoPoint point) {
boolean isWithin(final Vector point);
/** Check if point is within this endpoint.
*@param x is the point x.
*@param y is the point y.
*@param z is the point z.
*@return true of within.
*/
boolean isWithin(final double x, final double y, final double z);
/** Compute delta path distance.
*@param distanceStyle is the distance style.
*@param x is the point x.
*@param y is the point y.
*@param z is the point z.
*@return the distance metric, in aggregation form.
*/
double pathDeltaDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
/** Compute interior path distance.
*@param distanceStyle is the distance style.
*@param x is the point x.
*@param y is the point y.
*@param z is the point z.
*@return the distance metric, in aggregation form.
*/
double pathDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
/** Compute nearest path distance.
*@param distanceStyle is the distance style.
*@param x is the point x.
*@param y is the point y.
*@param z is the point z.
*@return the distance metric (always value zero), in aggregation form, or POSITIVE_INFINITY
* if the point is not within the bounds of the endpoint.
*/
double nearestPathDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
/** Compute path center distance.
*@param distanceStyle is the distance style.
*@param x is the point x.
*@param y is the point y.
*@param z is the point z.
*@return the distance metric, or POSITIVE_INFINITY
* if the point is not within the bounds of the endpoint.
*/
double pathCenterDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
/** Compute external distance.
*@param distanceStyle is the distance style.
*@param x is the point x.
*@param y is the point y.
*@param z is the point z.
*@return the distance metric.
*/
double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
/** Determine if this endpoint intersects a specified plane.
*@param planetModel is the planet model.
*@param p is the plane.
*@param notablePoints are the points associated with the plane.
*@param bounds are any bounds which the intersection must lie within.
*@return true if there is a matching intersection.
*/
boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds);
/** Determine if this endpoint intersects a GeoShape.
*@param geoShape is the GeoShape.
*@return true if there is shape intersect this endpoint.
*/
boolean intersects(final GeoShape geoShape);
/** Get the bounds for a segment endpoint.
*@param planetModel is the planet model.
*@param bounds are the bounds to be modified.
*/
void getBounds(final PlanetModel planetModel, Bounds bounds);
}
/**
* Base implementation of SegmentEndpoint
*/
private static class BaseSegmentEndpoint implements SegmentEndpoint {
/** The center point of the endpoint */
protected final GeoPoint point;
/** Null membership */
protected final static Membership[] NO_MEMBERSHIP = new Membership[0];
public BaseSegmentEndpoint(final GeoPoint point) {
this.point = point;
this.circlePlane = null;
this.cutoffPlanes = null;
this.notablePoints = null;
}
@Override
public boolean isWithin(final Vector point) {
return false;
}
@Override
public boolean isWithin(final double x, final double y, final double z) {
return false;
}
@Override
public double pathDeltaDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
if (!isWithin(x,y,z))
return Double.POSITIVE_INFINITY;
final double theDistance = distanceStyle.toAggregationForm(distanceStyle.computeDistance(this.point, x, y, z));
return distanceStyle.aggregateDistances(theDistance, theDistance);
}
@Override
public double pathDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
if (!isWithin(x,y,z))
return Double.POSITIVE_INFINITY;
return distanceStyle.toAggregationForm(distanceStyle.computeDistance(this.point, x, y, z));
}
@Override
public double nearestPathDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
return distanceStyle.toAggregationForm(0.0);
}
@Override
public double pathCenterDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
return distanceStyle.computeDistance(this.point, x, y, z);
}
@Override
public double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
return distanceStyle.computeDistance(this.point, x, y, z);
}
@Override
public boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
return false;
}
@Override
public boolean intersects(final GeoShape geoShape) {
return false;
}
@Override
public void getBounds(final PlanetModel planetModel, Bounds bounds) {
bounds.addPoint(point);
}
@Override
public boolean equals(final Object o) {
if (!(o instanceof BaseSegmentEndpoint))
return false;
final BaseSegmentEndpoint other = (BaseSegmentEndpoint) o;
return point.equals(other.point);
}
@Override
public int hashCode() {
return point.hashCode();
}
@Override
public String toString() {
return point.toString();
}
}
/**
* Simplest possible implementation of segment endpoint: a single point.
*/
private static class DegenerateSegmentEndpoint extends BaseSegmentEndpoint {
public DegenerateSegmentEndpoint(final GeoPoint point) {
super(point);
}
}
/**
* Endpoint that's a simple circle.
*/
private static class CircleSegmentEndpoint extends BaseSegmentEndpoint {
/** A plane describing the circle */
protected final SidedPlane circlePlane;
/** No notable points from the circle itself */
protected final static GeoPoint[] circlePoints = new GeoPoint[0];
/** Constructor for case (1).
* Generate a simple circle cutoff plane.
*@param point is the center point.
*@param upperPoint is a point that must be on the circle plane.
*@param lowerPoint is another point that must be on the circle plane.
*/
public SegmentEndpoint(final GeoPoint point, final Plane normalPlane, final GeoPoint upperPoint, final GeoPoint lowerPoint) {
this.point = point;
public CircleSegmentEndpoint(final GeoPoint point, final Plane normalPlane, final GeoPoint upperPoint, final GeoPoint lowerPoint) {
super(point);
// Construct a sided plane that goes through the two points and whose normal is in the normalPlane.
this.circlePlane = SidedPlane.constructNormalizedPerpendicularSidedPlane(point, normalPlane, upperPoint, lowerPoint);
this.cutoffPlanes = NO_MEMBERSHIP;
this.notablePoints = circlePoints;
}
/** Constructor for case (3). Called by superclass only.
*@param point is the center point.
*@param circlePlane is the circle plane.
*/
protected CircleSegmentEndpoint(final GeoPoint point, final SidedPlane circlePlane) {
super(point);
this.circlePlane = circlePlane;
}
@Override
public boolean isWithin(final Vector point) {
return circlePlane.isWithin(point);
}
@Override
public boolean isWithin(final double x, final double y, final double z) {
return circlePlane.isWithin(x, y, z);
}
@Override
public boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
return circlePlane.intersects(planetModel, p, notablePoints, circlePoints, bounds);
}
@Override
public boolean intersects(final GeoShape geoShape) {
return geoShape.intersects(circlePlane, circlePoints, NO_MEMBERSHIP);
}
@Override
public void getBounds(final PlanetModel planetModel, Bounds bounds) {
super.getBounds(planetModel, bounds);
bounds.addPlane(planetModel, circlePlane);
}
}
/**
* Endpoint that's a single circle with cutoff(s).
*/
private static class CutoffSingleCircleSegmentEndpoint extends CircleSegmentEndpoint {
/** Pertinent cutoff plane from adjoining segments */
protected final Membership[] cutoffPlanes;
/** Notable points for this segment endpoint */
private final GeoPoint[] notablePoints;
/** Constructor for case (2).
* Generate an endpoint, given a single cutoff plane plus upper and lower edge points.
*@param point is the center point.
@ -511,13 +727,11 @@ class GeoStandardPath extends GeoBasePath {
*@param topEdgePoint is a point on the cutoffPlane that should be also on the circle plane.
*@param bottomEdgePoint is another point on the cutoffPlane that should be also on the circle plane.
*/
public SegmentEndpoint(final GeoPoint point,
public CutoffSingleCircleSegmentEndpoint(final GeoPoint point,
final SidedPlane cutoffPlane, final GeoPoint topEdgePoint, final GeoPoint bottomEdgePoint) {
this.point = point;
super(point, cutoffPlane, topEdgePoint, bottomEdgePoint);
this.cutoffPlanes = new Membership[]{new SidedPlane(cutoffPlane)};
this.notablePoints = new GeoPoint[]{topEdgePoint, bottomEdgePoint};
// To construct the plane, we now just need D, which is simply the negative of the evaluation of the circle normal vector at one of the points.
this.circlePlane = SidedPlane.constructNormalizedPerpendicularSidedPlane(point, cutoffPlane, topEdgePoint, bottomEdgePoint);
}
/** Constructor for case (2.5).
@ -528,15 +742,85 @@ class GeoStandardPath extends GeoBasePath {
*@param topEdgePoint is a point on the cutoffPlane that should be also on the circle plane.
*@param bottomEdgePoint is another point on the cutoffPlane that should be also on the circle plane.
*/
public SegmentEndpoint(final GeoPoint point,
public CutoffSingleCircleSegmentEndpoint(final GeoPoint point,
final SidedPlane cutoffPlane1, final SidedPlane cutoffPlane2, final GeoPoint topEdgePoint, final GeoPoint bottomEdgePoint) {
this.point = point;
super(point, cutoffPlane1, topEdgePoint, bottomEdgePoint);
this.cutoffPlanes = new Membership[]{new SidedPlane(cutoffPlane1), new SidedPlane(cutoffPlane2)};
this.notablePoints = new GeoPoint[]{topEdgePoint, bottomEdgePoint};
// To construct the plane, we now just need D, which is simply the negative of the evaluation of the circle normal vector at one of the points.
this.circlePlane = SidedPlane.constructNormalizedPerpendicularSidedPlane(point, cutoffPlane1, topEdgePoint, bottomEdgePoint);
}
@Override
public boolean isWithin(final Vector point) {
if (!super.isWithin(point)) {
return false;
}
for (final Membership m : cutoffPlanes) {
if (!m.isWithin(point)) {
return false;
}
}
return true;
}
@Override
public boolean isWithin(final double x, final double y, final double z) {
if (!super.isWithin(x, y, z)) {
return false;
}
for (final Membership m : cutoffPlanes) {
if (!m.isWithin(x,y,z)) {
return false;
}
}
return true;
}
@Override
public double nearestPathDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
for (final Membership m : cutoffPlanes) {
if (!m.isWithin(x,y,z)) {
return Double.POSITIVE_INFINITY;
}
}
return super.nearestPathDistance(distanceStyle, x, y, z);
}
@Override
public double pathCenterDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
for (final Membership m : cutoffPlanes) {
if (!m.isWithin(x,y,z)) {
return Double.POSITIVE_INFINITY;
}
}
return super.pathCenterDistance(distanceStyle, x, y, z);
}
@Override
public boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
return circlePlane.intersects(planetModel, p, notablePoints, this.notablePoints, bounds, this.cutoffPlanes);
}
@Override
public boolean intersects(final GeoShape geoShape) {
return geoShape.intersects(circlePlane, this.notablePoints, this.cutoffPlanes);
}
}
/**
* Endpoint that's a dual circle with cutoff(s).
*/
private static class CutoffDualCircleSegmentEndpoint extends BaseSegmentEndpoint {
// For now, keep the old implementation
// MHL
protected final SidedPlane circlePlane;
/** Pertinent cutoff plane from adjoining segments */
protected final Membership[] cutoffPlanes;
/** Notable points for this segment endpoint */
private final GeoPoint[] notablePoints;
/** Constructor for case (3).
* Generate an endpoint for an intersection, given four points.
*@param point is the center.
@ -551,7 +835,7 @@ class GeoStandardPath extends GeoBasePath {
*@param candidate3 one of four candidate circle planes.
*@param candidate4 one of four candidate circle planes.
*/
public SegmentEndpoint(final GeoPoint point,
public CutoffDualCircleSegmentEndpoint(final GeoPoint point,
final SidedPlane prevCutoffPlane, final SidedPlane nextCutoffPlane,
final GeoPoint notCand2Point, final GeoPoint notCand1Point,
final GeoPoint notCand3Point, final GeoPoint notCand4Point,
@ -565,8 +849,8 @@ class GeoStandardPath extends GeoBasePath {
// The solution is to look for the side (top or bottom) that has an intersection within the shape. We use the two points from
// the opposite side to determine the plane, AND we pick the third to be either of the two points on the intersecting side
// PROVIDED that the other point is within the final circle we come up with.
this.point = point;
super(point);
// We construct four separate planes, and evaluate which one includes all interior points with least overlap
// (Constructed beforehand because we need them for degeneracy check)
@ -591,7 +875,7 @@ class GeoStandardPath extends GeoBasePath {
this.notablePoints = new GeoPoint[]{notCand3Point, notCand4Point, notCand1Point};
this.cutoffPlanes = new Membership[]{new SidedPlane(nextCutoffPlane)};
} else if (cand3IsOtherWithin) {
this.circlePlane = candidate3;
circlePlane = candidate3;
this.notablePoints = new GeoPoint[]{notCand4Point, notCand1Point, notCand2Point};
this.cutoffPlanes = new Membership[]{new SidedPlane(prevCutoffPlane)};
} else if (cand4IsOtherWithin) {
@ -604,15 +888,11 @@ class GeoStandardPath extends GeoBasePath {
}
}
/** Check if point is within this endpoint.
*@param point is the point.
*@return true of within.
*/
@Override
public boolean isWithin(final Vector point) {
if (circlePlane == null)
return false;
if (!circlePlane.isWithin(point))
if (!circlePlane.isWithin(point)) {
return false;
}
for (final Membership m : cutoffPlanes) {
if (!m.isWithin(point)) {
return false;
@ -621,17 +901,11 @@ class GeoStandardPath extends GeoBasePath {
return true;
}
/** Check if point is within this endpoint.
*@param x is the point x.
*@param y is the point y.
*@param z is the point z.
*@return true of within.
*/
@Override
public boolean isWithin(final double x, final double y, final double z) {
if (circlePlane == null)
return false;
if (!circlePlane.isWithin(x, y, z))
if (!circlePlane.isWithin(x, y, z)) {
return false;
}
for (final Membership m : cutoffPlanes) {
if (!m.isWithin(x,y,z)) {
return false;
@ -640,133 +914,44 @@ class GeoStandardPath extends GeoBasePath {
return true;
}
/** Compute delta path distance.
*@param distanceStyle is the distance style.
*@param x is the point x.
*@param y is the point y.
*@param z is the point z.
*@return the distance metric, in aggregation form.
*/
public double pathDeltaDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
if (!isWithin(x,y,z))
return Double.POSITIVE_INFINITY;
final double theDistance = distanceStyle.toAggregationForm(distanceStyle.computeDistance(this.point, x, y, z));
return distanceStyle.aggregateDistances(theDistance, theDistance);
}
/** Compute interior path distance.
*@param distanceStyle is the distance style.
*@param x is the point x.
*@param y is the point y.
*@param z is the point z.
*@return the distance metric, in aggregation form.
*/
public double pathDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
if (!isWithin(x,y,z))
return Double.POSITIVE_INFINITY;
return distanceStyle.toAggregationForm(distanceStyle.computeDistance(this.point, x, y, z));
}
/** Compute nearest path distance.
*@param distanceStyle is the distance style.
*@param x is the point x.
*@param y is the point y.
*@param z is the point z.
*@return the distance metric (always value zero), in aggregation form, or POSITIVE_INFINITY
* if the point is not within the bounds of the endpoint.
*/
@Override
public double nearestPathDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
for (final Membership m : cutoffPlanes) {
if (!m.isWithin(x,y,z)) {
return Double.POSITIVE_INFINITY;
}
}
return distanceStyle.toAggregationForm(0.0);
return super.nearestPathDistance(distanceStyle, x, y, z);
}
/** Compute path center distance.
*@param distanceStyle is the distance style.
*@param x is the point x.
*@param y is the point y.
*@param z is the point z.
*@return the distance metric, or POSITIVE_INFINITY
* if the point is not within the bounds of the endpoint.
*/
@Override
public double pathCenterDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
for (final Membership m : cutoffPlanes) {
if (!m.isWithin(x,y,z)) {
return Double.POSITIVE_INFINITY;
}
}
return distanceStyle.computeDistance(this.point, x, y, z);
return super.pathCenterDistance(distanceStyle, x, y, z);
}
/** Compute external distance.
*@param distanceStyle is the distance style.
*@param x is the point x.
*@param y is the point y.
*@param z is the point z.
*@return the distance metric.
*/
public double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
return distanceStyle.computeDistance(this.point, x, y, z);
}
/** Determine if this endpoint intersects a specified plane.
*@param planetModel is the planet model.
*@param p is the plane.
*@param notablePoints are the points associated with the plane.
*@param bounds are any bounds which the intersection must lie within.
*@return true if there is a matching intersection.
*/
@Override
public boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
//System.err.println(" looking for intersection between plane "+p+" and circle "+circlePlane+" on proper side of "+cutoffPlanes+" within "+bounds);
if (circlePlane == null)
return false;
return circlePlane.intersects(planetModel, p, notablePoints, this.notablePoints, bounds, this.cutoffPlanes);
}
/** Determine if this endpoint intersects a GeoShape.
*@param geoShape is the GeoShape.
*@return true if there is shape intersect this endpoint.
*/
@Override
public boolean intersects(final GeoShape geoShape) {
//System.err.println(" looking for intersection between plane "+p+" and circle "+circlePlane+" on proper side of "+cutoffPlanes+" within "+bounds);
if (circlePlane == null)
return false;
return geoShape.intersects(circlePlane, this.notablePoints, this.cutoffPlanes);
}
/** Get the bounds for a segment endpoint.
*@param planetModel is the planet model.
*@param bounds are the bounds to be modified.
*/
@Override
public void getBounds(final PlanetModel planetModel, Bounds bounds) {
bounds.addPoint(point);
if (circlePlane == null)
return;
super.getBounds(planetModel, bounds);
bounds.addPlane(planetModel, circlePlane);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof SegmentEndpoint))
return false;
SegmentEndpoint other = (SegmentEndpoint) o;
return point.equals(other.point);
}
@Override
public int hashCode() {
return point.hashCode();
}
@Override
public String toString() {
return point.toString();
}
}
/**
* This is the pre-calculated data for a path segment.
*/
@ -1118,6 +1303,11 @@ class GeoStandardPath extends GeoBasePath {
public boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
return upperConnectingPlane.intersects(planetModel, p, notablePoints, upperConnectingPlanePoints, bounds, lowerConnectingPlane, startCutoffPlane, endCutoffPlane) ||
lowerConnectingPlane.intersects(planetModel, p, notablePoints, lowerConnectingPlanePoints, bounds, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
/* ||
// These two are necessary because our segment endpoints are not necessarily good fits to their adjoining segments. The checks should really be part of the segment endpoint, however
startCutoffPlane.intersects(planetModel, p, notablePoints, startCutoffPlanePoints, bounds, endCutoffPlane, upperConnectingPlane, lowerConnectingPlane) ||
endCutoffPlane.intersects(planetModel, p, notablePoints, endCutoffPlanePoints, bounds, startCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
*/
}
/** Determine if this endpoint intersects a specified GeoShape.
@ -1127,6 +1317,11 @@ class GeoStandardPath extends GeoBasePath {
public boolean intersects(final GeoShape geoShape) {
return geoShape.intersects(upperConnectingPlane, upperConnectingPlanePoints, lowerConnectingPlane, startCutoffPlane, endCutoffPlane) ||
geoShape.intersects(lowerConnectingPlane, lowerConnectingPlanePoints, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
/*||
// These two are necessary because our segment endpoints are not necessarily good fits to their adjoining segments. The checks should really be part of the segment endpoint, however
geoShape.intersects(startCutoffPlane, startCutoffPlanePoints, endCutoffPlane, upperConnectingPlane, lowerConnectingPlane) ||
geoShape.intersects(endCutoffPlane, endCutoffPlanePoints, startCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
*/
}
/** Get the bounds for a segment endpoint.

View File

@ -411,6 +411,8 @@ public class GeoPathTest extends LuceneTestCase {
points[3] = new GeoPoint(PlanetModel.WGS84, -0.7718789008737459, 0.9236607495528212);
GeoPath path = GeoPathFactory.makeGeoPath(PlanetModel.WGS84, 1.3439035240356338, points);
GeoPoint check = new GeoPoint(0.02071783020158524, 0.9523290535474472, 0.30699177256064203);
// Map to surface point, to remove that source of confusion
GeoPoint surfaceCheck = PlanetModel.WGS84.createSurfacePoint(check);
/*
[junit4] 1> cycle: cell=12502 parentCellID=12500 x: -1658490249 TO 2147483041, y: 2042111310 TO 2147483041, z: -2140282940 TO 2140277970, splits: 1 queue.size()=1
[junit4] 1> minx=-0.7731590077686981 maxx=1.0011188539924791 miny=0.9519964046486451 maxy=1.0011188539924791 minz=-0.9977622932859775 maxz=0.9977599768255027
@ -421,15 +423,14 @@ public class GeoPathTest extends LuceneTestCase {
0.9519964046486451, 1.0011188539924791,
-0.9977622932859775, 0.9977599768255027);
// Verify that the point is within it
assertTrue(solid.isWithin(check));
// Check the relationship
assertTrue(solid.isWithin(surfaceCheck));
// Check the (surface) relationship
int relationship = solid.getRelationship(path);
assertTrue(relationship == GeoArea.CONTAINS);
// If relationship is CONTAINS then any point in the solid must also be within the path
// If point is within solid, it must be within shape
assertTrue(path.isWithin(check));
//GeoPoint surfaceCheck = PlanetModel.WGS84.createSurfacePoint(check);
if (relationship == GeoArea.CONTAINS) {
// If relationship is CONTAINS then any point in the solid must also be within the path
// If point is within solid, it must be within shape
assertTrue(path.isWithin(surfaceCheck));
}
}