diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePath.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePath.java index b13bbfe50ff..472dedb158f 100644 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePath.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePath.java @@ -21,9 +21,9 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * GeoShape representing a path across the surface of the globe, with a specified half-width. Path @@ -109,7 +109,7 @@ class GeoDegeneratePath extends GeoBasePath { // Simple circle final GeoPoint point = points.get(0); - final SegmentEndpoint onlyEndpoint = new SegmentEndpoint(point); + final SegmentEndpoint onlyEndpoint = new SegmentEndpoint(planetModel, point); endPoints.add(onlyEndpoint); this.edgePoints = new GeoPoint[] {point}; return; @@ -122,7 +122,7 @@ class GeoDegeneratePath extends GeoBasePath { if (i == 0) { // Starting endpoint final SegmentEndpoint startEndpoint = - new SegmentEndpoint(currentSegment.start, currentSegment.startCutoffPlane); + new SegmentEndpoint(planetModel, currentSegment.start, currentSegment.startCutoffPlane); endPoints.add(startEndpoint); this.edgePoints = new GeoPoint[] {currentSegment.start}; continue; @@ -130,13 +130,14 @@ class GeoDegeneratePath extends GeoBasePath { endPoints.add( new SegmentEndpoint( + planetModel, currentSegment.start, segments.get(i - 1).endCutoffPlane, currentSegment.startCutoffPlane)); } // Do final endpoint final PathSegment lastSegment = segments.get(segments.size() - 1); - endPoints.add(new SegmentEndpoint(lastSegment.end, lastSegment.endCutoffPlane)); + endPoints.add(new SegmentEndpoint(planetModel, lastSegment.end, lastSegment.endCutoffPlane)); } /** @@ -162,8 +163,7 @@ class GeoDegeneratePath extends GeoBasePath { double closestDistance = Double.POSITIVE_INFINITY; // Segments first for (PathSegment segment : segments) { - final double segmentDistance = - segment.pathCenterDistance(planetModel, distanceStyle, x, y, z); + final double segmentDistance = segment.pathCenterDistance(distanceStyle, x, y, z); if (segmentDistance < closestDistance) { closestDistance = segmentDistance; } @@ -196,14 +196,12 @@ class GeoDegeneratePath extends GeoBasePath { // Look at the following segment, if any if (segmentIndex < segments.size()) { final PathSegment segment = segments.get(segmentIndex++); - final double segmentPathCenterDistance = - segment.pathCenterDistance(planetModel, distanceStyle, x, y, z); + final double segmentPathCenterDistance = segment.pathCenterDistance(distanceStyle, x, y, z); if (segmentPathCenterDistance < minPathCenterDistance) { minPathCenterDistance = segmentPathCenterDistance; bestDistance = distanceStyle.aggregateDistances( - currentDistance, - segment.nearestPathDistance(planetModel, distanceStyle, x, y, z)); + currentDistance, segment.nearestPathDistance(distanceStyle, x, y, z)); } currentDistance = distanceStyle.aggregateDistances( @@ -221,7 +219,7 @@ class GeoDegeneratePath extends GeoBasePath { // (2) If the point is within any of the segment end circles along the path, return that value. double currentDistance = 0.0; for (PathSegment segment : segments) { - double distance = segment.pathDistance(planetModel, distanceStyle, x, y, z); + double distance = segment.pathDistance(distanceStyle, x, y, z); if (distance != Double.POSITIVE_INFINITY) return distanceStyle.fromAggregationForm( distanceStyle.aggregateDistances(currentDistance, distance)); @@ -272,7 +270,7 @@ class GeoDegeneratePath extends GeoBasePath { } } for (final PathSegment segment : segments) { - final double newDistance = segment.outsideDistance(planetModel, distanceStyle, x, y, z); + final double newDistance = segment.outsideDistance(distanceStyle, x, y, z); if (newDistance < minDistance) { minDistance = newDistance; } @@ -317,11 +315,11 @@ class GeoDegeneratePath extends GeoBasePath { // Since the endpoints are included in the path segments, we only need to do this if there are // no path segments if (endPoints.size() == 1) { - return endPoints.get(0).intersects(planetModel, plane, notablePoints, bounds); + return endPoints.get(0).intersects(plane, notablePoints, bounds); } for (final PathSegment pathSegment : segments) { - if (pathSegment.intersects(planetModel, plane, notablePoints, bounds)) { + if (pathSegment.intersects(plane, notablePoints, bounds)) { return true; } } @@ -353,10 +351,10 @@ class GeoDegeneratePath extends GeoBasePath { // never more than 180 degrees longitude at a pop or we risk having the // bounds object get itself inverted. So do the edges first. for (PathSegment pathSegment : segments) { - pathSegment.getBounds(planetModel, bounds); + pathSegment.getBounds(bounds); } if (endPoints.size() == 1) { - endPoints.get(0).getBounds(planetModel, bounds); + endPoints.get(0).getBounds(bounds); } } @@ -396,7 +394,7 @@ class GeoDegeneratePath extends GeoBasePath { *
  • Intersection. There are two cutoff planes, one for each end of the intersection. * */ - private static class SegmentEndpoint { + private static class SegmentEndpoint extends GeoBaseBounds { /** The center point of the endpoint */ public final GeoPoint point; /** Pertinent cutoff planes from adjoining segments */ @@ -407,9 +405,11 @@ class GeoDegeneratePath extends GeoBasePath { /** * Constructor for case (1). * + * @param planetModel is the planet model. * @param point is the center point. */ - public SegmentEndpoint(final GeoPoint point) { + public SegmentEndpoint(final PlanetModel planetModel, final GeoPoint point) { + super(planetModel); this.point = point; this.cutoffPlanes = NO_MEMBERSHIP; } @@ -422,7 +422,9 @@ class GeoDegeneratePath extends GeoBasePath { * @param cutoffPlane is the plane from the adjoining path segment marking the boundary between * this endpoint and that segment. */ - public SegmentEndpoint(final GeoPoint point, final SidedPlane cutoffPlane) { + public SegmentEndpoint( + final PlanetModel planetModel, final GeoPoint point, final SidedPlane cutoffPlane) { + super(planetModel); this.point = point; this.cutoffPlanes = new Membership[] {new SidedPlane(cutoffPlane)}; } @@ -430,12 +432,17 @@ class GeoDegeneratePath extends GeoBasePath { /** * Constructor for case (3). Generate an endpoint, given two cutoff planes. * + * @param planetModel is the planet model. * @param point is the center. * @param cutoffPlane1 is one adjoining path segment cutoff plane. * @param cutoffPlane2 is another adjoining path segment cutoff plane. */ public SegmentEndpoint( - final GeoPoint point, final SidedPlane cutoffPlane1, final SidedPlane cutoffPlane2) { + final PlanetModel planetModel, + final GeoPoint point, + final SidedPlane cutoffPlane1, + final SidedPlane cutoffPlane2) { + super(planetModel); this.point = point; this.cutoffPlanes = new Membership[] {new SidedPlane(cutoffPlane1), new SidedPlane(cutoffPlane2)}; @@ -507,17 +514,13 @@ class GeoDegeneratePath extends GeoBasePath { /** * 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. */ public boolean intersects( - final PlanetModel planetModel, - final Plane p, - final GeoPoint[] notablePoints, - final Membership[] bounds) { + final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) { // If not on the plane, no intersection if (!p.evaluateIsZero(point)) { return false; @@ -572,13 +575,13 @@ class GeoDegeneratePath extends GeoBasePath { } /** This is the pre-calculated data for a path segment. */ - private static class PathSegment { + private static class PathSegment extends GeoBaseBounds { /** Starting point of the segment */ public final GeoPoint start; /** End point of the segment */ public final GeoPoint end; /** Place to keep any complete segment distances we've calculated so far */ - public final Map fullDistanceCache = new HashMap<>(); + public final Map fullDistanceCache = new ConcurrentHashMap<>(1); /** Normalized plane connecting the two points and going through world center */ public final Plane normalizedConnectingPlane; /** Plane going through the center and start point, marking the start edge of the segment */ @@ -601,6 +604,7 @@ class GeoDegeneratePath extends GeoBasePath { final GeoPoint start, final GeoPoint end, final Plane normalizedConnectingPlane) { + super(planetModel); this.start = start; this.end = end; this.normalizedConnectingPlane = normalizedConnectingPlane; @@ -618,16 +622,14 @@ class GeoDegeneratePath extends GeoBasePath { * @return the distance metric, in aggregation form. */ public double fullPathDistance(final DistanceStyle distanceStyle) { - synchronized (fullDistanceCache) { - Double dist = fullDistanceCache.get(distanceStyle); - if (dist == null) { - dist = - distanceStyle.toAggregationForm( - distanceStyle.computeDistance(start, end.x, end.y, end.z)); - fullDistanceCache.put(distanceStyle, dist); - } - return dist.doubleValue(); + Double dist = fullDistanceCache.get(distanceStyle); + if (dist == null) { + dist = + distanceStyle.toAggregationForm( + distanceStyle.computeDistance(start, end.x, end.y, end.z)); + fullDistanceCache.put(distanceStyle, dist); } + return dist.doubleValue(); } /** @@ -638,6 +640,7 @@ class GeoDegeneratePath extends GeoBasePath { * @param z is the point z. * @return true of within. */ + @Override public boolean isWithin(final double x, final double y, final double z) { return startCutoffPlane.isWithin(x, y, z) && endCutoffPlane.isWithin(x, y, z) @@ -645,9 +648,8 @@ class GeoDegeneratePath extends GeoBasePath { } /** - * Compute path center distance. + * Compute path center distance (distance from path to current point). * - * @param planetModel is the planet model. * @param distanceStyle is the distance style. * @param x is the point x. * @param y is the point y. @@ -655,11 +657,7 @@ class GeoDegeneratePath extends GeoBasePath { * @return the distance metric, or Double.POSITIVE_INFINITY if outside this segment */ public double pathCenterDistance( - final PlanetModel planetModel, - final DistanceStyle distanceStyle, - final double x, - final double y, - final double z) { + final DistanceStyle distanceStyle, final double x, final double y, final double z) { // First, if this point is outside the endplanes of the segment, return POSITIVE_INFINITY. if (!startCutoffPlane.isWithin(x, y, z) || !endCutoffPlane.isWithin(x, y, z)) { return Double.POSITIVE_INFINITY; @@ -704,9 +702,8 @@ class GeoDegeneratePath extends GeoBasePath { } /** - * Compute nearest path distance. + * Compute nearest path distance (distance from start of segment to center line point adjacent). * - * @param planetModel is the planet model. * @param distanceStyle is the distance style. * @param x is the point x. * @param y is the point y. @@ -715,11 +712,7 @@ class GeoDegeneratePath extends GeoBasePath { * segment */ public double nearestPathDistance( - final PlanetModel planetModel, - final DistanceStyle distanceStyle, - final double x, - final double y, - final double z) { + final DistanceStyle distanceStyle, final double x, final double y, final double z) { // First, if this point is outside the endplanes of the segment, return POSITIVE_INFINITY. if (!startCutoffPlane.isWithin(x, y, z) || !endCutoffPlane.isWithin(x, y, z)) { return Double.POSITIVE_INFINITY; @@ -775,11 +768,7 @@ class GeoDegeneratePath extends GeoBasePath { * @return the distance metric, in aggregation form. */ public double pathDistance( - final PlanetModel planetModel, - final DistanceStyle distanceStyle, - final double x, - final double y, - final double z) { + final DistanceStyle distanceStyle, final double x, final double y, final double z) { if (!isWithin(x, y, z)) return Double.POSITIVE_INFINITY; // (1) Compute normalizedPerpPlane. If degenerate, then return point distance from start to @@ -839,11 +828,7 @@ class GeoDegeneratePath extends GeoBasePath { * @return the distance metric. */ public double outsideDistance( - final PlanetModel planetModel, - final DistanceStyle distanceStyle, - final double x, - final double y, - final double z) { + final DistanceStyle distanceStyle, final double x, final double y, final double z) { final double distance = distanceStyle.computeDistance( planetModel, normalizedConnectingPlane, x, y, z, startCutoffPlane, endCutoffPlane); @@ -862,10 +847,7 @@ class GeoDegeneratePath extends GeoBasePath { * @return true if there is a matching intersection. */ public boolean intersects( - final PlanetModel planetModel, - final Plane p, - final GeoPoint[] notablePoints, - final Membership[] bounds) { + final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) { return normalizedConnectingPlane.intersects( planetModel, p, @@ -893,7 +875,9 @@ class GeoDegeneratePath extends GeoBasePath { * @param planetModel is the planet model. * @param bounds are the bounds to be modified. */ - public void getBounds(final PlanetModel planetModel, Bounds bounds) { + @Override + public void getBounds(final Bounds bounds) { + super.getBounds(bounds); // We need to do all bounding planes as well as corner points bounds .addPoint(start) diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoStandardPath.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoStandardPath.java index 4d711a1efa3..072b276cd4a 100755 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoStandardPath.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoStandardPath.java @@ -108,7 +108,7 @@ class GeoStandardPath extends GeoBasePath { final List endPoints = new ArrayList<>(points.size()); final List segments = new ArrayList<>(points.size()); - + // Compute an offset to use for all segments. This will be based on the minimum magnitude of // the entire ellipsoid. final double cutoffOffset = this.sinAngle * planetModel.getMinimumMagnitude(); @@ -351,7 +351,11 @@ class GeoStandardPath extends GeoBasePath { if (rootComponent == null) { return false; } - return rootComponent.intersects(plane, notablePoints, bounds); + final boolean rval = rootComponent.intersects(plane, notablePoints, bounds); + if (rval) { + System.out.println("Plane " + plane + " within its bounds intersects " + rootComponent); + } + return rval; } @Override @@ -359,7 +363,11 @@ class GeoStandardPath extends GeoBasePath { if (rootComponent == null) { return false; } - return rootComponent.intersects(geoShape); + final boolean rval = rootComponent.intersects(geoShape); + if (rval) { + System.out.println("Shape " + geoShape + " intersects " + rootComponent); + } + return rval; } @Override @@ -430,6 +438,12 @@ class GeoStandardPath extends GeoBasePath { */ boolean isWithin(final double x, final double y, final double z); + /** Check if point is within this section (within cutoff planes). */ + boolean isWithinSection(final Vector point); + + /** Check if point is within this section (within cutoff planes). */ + boolean isWithinSection(final double x, final double y, final double z); + /** * Retrieve the starting distance along the path for this path element. * @@ -498,28 +512,28 @@ class GeoStandardPath extends GeoBasePath { final DistanceStyle distanceStyle, final double x, final double y, final double z); /** - * Compute nearest path distance. + * Compute nearest path distance (distance from start of segment to point adjacent the one + * specitied, if reachable by this segment). * * @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. + * @return the distance metric, in aggregation form. */ double nearestPathDistance( final DistanceStyle distanceStyle, final double x, final double y, final double z); /** - * Compute path center distance. Returns POSITIVE_INFINITY if the point is outside of the - * bounds. + * Compute path center distance (distance from the point to center of the path, if reachable by + * this segment). * * @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. + * the path segment. */ double pathCenterDistance( final DistanceStyle distanceStyle, final double x, final double y, final double z); @@ -611,6 +625,16 @@ class GeoStandardPath extends GeoBasePath { return child1.isWithin(x, y, z) || child2.isWithin(x, y, z); } + @Override + public boolean isWithinSection(final Vector point) { + return child1.isWithinSection(point) || child2.isWithinSection(point); + } + + @Override + public boolean isWithinSection(final double x, final double y, final double z) { + return child1.isWithinSection(x, y, z) || child2.isWithinSection(x, y, z); + } + @Override public double getStartingDistance(final DistanceStyle distanceStyle) { return child1.getStartingDistance(distanceStyle); @@ -632,7 +656,7 @@ class GeoStandardPath extends GeoBasePath { @Override public double nearestDistance( final DistanceStyle distanceStyle, final double x, final double y, final double z) { - if (!isWithin(x, y, z)) { + if (!isWithinSection(x, y, z)) { return Double.POSITIVE_INFINITY; } return Math.min( @@ -672,7 +696,7 @@ class GeoStandardPath extends GeoBasePath { @Override public double nearestPathDistance( final DistanceStyle distanceStyle, final double x, final double y, final double z) { - if (!isWithin(x, y, z)) { + if (!isWithinSection(x, y, z)) { return Double.POSITIVE_INFINITY; } return Math.min( @@ -683,7 +707,7 @@ class GeoStandardPath extends GeoBasePath { @Override public double pathCenterDistance( final DistanceStyle distanceStyle, final double x, final double y, final double z) { - if (!isWithin(x, y, z)) { + if (!isWithinSection(x, y, z)) { return Double.POSITIVE_INFINITY; } return Math.min( @@ -703,8 +727,17 @@ class GeoStandardPath extends GeoBasePath { @Override public boolean intersects( final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) { - return child1.intersects(p, notablePoints, bounds) - || child2.intersects(p, notablePoints, bounds); + final boolean rval = + child1.intersects(p, notablePoints, bounds) + || child2.intersects(p, notablePoints, bounds); + if (rval) { + if (child1.intersects(p, notablePoints, bounds)) { + System.out.println("Plane " + p + " intersected " + child1); + } else if (child2.intersects(p, notablePoints, bounds)) { + System.out.println("Plane " + p + " intersected " + child2); + } + } + return rval; } @Override @@ -769,6 +802,16 @@ class GeoStandardPath extends GeoBasePath { return false; } + @Override + public boolean isWithinSection(final double x, final double y, final double z) { + return true; + } + + @Override + public boolean isWithinSection(final Vector point) { + return true; + } + @Override public double getStartingDistance(DistanceStyle distanceStyle) { if (previous == null) { @@ -793,7 +836,7 @@ class GeoStandardPath extends GeoBasePath { @Override public double nearestDistance( final DistanceStyle distanceStyle, final double x, final double y, final double z) { - if (!isWithin(x, y, z)) { + if (!isWithinSection(x, y, z)) { return Double.POSITIVE_INFINITY; } return distanceStyle.fromAggregationForm(getStartingDistance(distanceStyle)); @@ -827,16 +870,16 @@ class GeoStandardPath extends GeoBasePath { @Override public double nearestPathDistance( final DistanceStyle distanceStyle, final double x, final double y, final double z) { - if (!isWithin(x, y, z)) { + if (!isWithinSection(x, y, z)) { return Double.POSITIVE_INFINITY; } - return distanceStyle.toAggregationForm(0.0); + return distanceStyle.toAggregationForm(distanceStyle.computeDistance(this.point, x, y, z)); } @Override public double pathCenterDistance( final DistanceStyle distanceStyle, final double x, final double y, final double z) { - if (!isWithin(x, y, z)) { + if (!isWithinSection(x, y, z)) { return Double.POSITIVE_INFINITY; } return distanceStyle.computeDistance(this.point, x, y, z); @@ -1023,6 +1066,16 @@ class GeoStandardPath extends GeoBasePath { return cutoffPlane.isWithin(x, y, z) && super.isWithin(x, y, z); } + @Override + public boolean isWithinSection(final Vector point) { + return cutoffPlane.isWithin(point); + } + + @Override + public boolean isWithinSection(final double x, final double y, final double z) { + return cutoffPlane.isWithin(x, y, z); + } + @Override public boolean intersects( final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) { @@ -1035,6 +1088,28 @@ class GeoStandardPath extends GeoBasePath { return geoShape.intersects(circlePlane, this.notablePoints, this.cutoffPlanes); } + @Override + public double nearestPathDistance( + final DistanceStyle distanceStyle, final double x, final double y, final double z) { + for (final Membership cutoff : cutoffPlanes) { + if (!cutoff.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 cutoff : cutoffPlanes) { + if (!cutoff.isWithin(x, y, z)) { + return Double.POSITIVE_INFINITY; + } + } + return super.pathCenterDistance(distanceStyle, x, y, z); + } + @Override public void getBounds(final Bounds bounds) { super.getBounds(bounds); @@ -1144,6 +1219,26 @@ class GeoStandardPath extends GeoBasePath { return circlePlane1.isWithin(x, y, z) || circlePlane2.isWithin(x, y, z); } + @Override + public boolean isWithinSection(final Vector point) { + for (final Membership m : cutoffPlanes) { + if (!m.isWithin(point)) { + return false; + } + } + return true; + } + + @Override + public boolean isWithinSection(final double x, final double y, final double z) { + for (final Membership m : cutoffPlanes) { + if (!m.isWithin(x, y, z)) { + return false; + } + } + return true; + } + @Override public boolean intersects( final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) { @@ -1159,6 +1254,28 @@ class GeoStandardPath extends GeoBasePath { || geoShape.intersects(circlePlane2, this.notablePoints2, this.cutoffPlanes); } + @Override + public double nearestPathDistance( + final DistanceStyle distanceStyle, final double x, final double y, final double z) { + for (final Membership cutoff : cutoffPlanes) { + if (!cutoff.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 cutoff : cutoffPlanes) { + if (!cutoff.isWithin(x, y, z)) { + return Double.POSITIVE_INFINITY; + } + } + return super.pathCenterDistance(distanceStyle, x, y, z); + } + @Override public void getBounds(final Bounds bounds) { super.getBounds(bounds); @@ -1311,6 +1428,16 @@ class GeoStandardPath extends GeoBasePath { return isWithin(v.x, v.y, v.z); } + @Override + public boolean isWithinSection(final Vector point) { + return startCutoffPlane.isWithin(point) && endCutoffPlane.isWithin(point); + } + + @Override + public boolean isWithinSection(final double x, final double y, final double z) { + return startCutoffPlane.isWithin(x, y, z) && endCutoffPlane.isWithin(x, y, z); + } + @Override public double getStartingDistance(final DistanceStyle distanceStyle) { Double dist = startDistanceCache.get(distanceStyle); @@ -1338,12 +1465,14 @@ class GeoStandardPath extends GeoBasePath { @Override public double nearestDistance( final DistanceStyle distanceStyle, final double x, final double y, final double z) { - if (!isWithin(x, y, z)) { + if (!isWithinSection(x, y, z)) { return Double.POSITIVE_INFINITY; } return distanceStyle.fromAggregationForm( distanceStyle.aggregateDistances( - getStartingDistance(distanceStyle), nearestPathDistance(distanceStyle, x, y, z))); + distanceStyle.aggregateDistances( + getStartingDistance(distanceStyle), nearestPathDistance(distanceStyle, x, y, z)), + pathCenterDistance(distanceStyle, x, y, z))); } private double computeStartingDistance(final DistanceStyle distanceStyle) { @@ -1358,10 +1487,10 @@ class GeoStandardPath extends GeoBasePath { public double pathCenterDistance( final DistanceStyle distanceStyle, final double x, final double y, final double z) { // Computes the distance to the path center from the specified point, or returns - // POSITIVE_INFINITY if the point is outside the path. + // POSITIVE_INFINITY if the point is outside the path section. // First, if this point is outside the endplanes of the segment, return POSITIVE_INFINITY. - if (!startCutoffPlane.isWithin(x, y, z) || !endCutoffPlane.isWithin(x, y, z)) { + if (!isWithinSection(x, y, z)) { return Double.POSITIVE_INFINITY; } // (1) Compute normalizedPerpPlane. If degenerate, then there is no such plane, which means @@ -1400,7 +1529,7 @@ class GeoStandardPath extends GeoBasePath { "Can't find world intersection for point x=" + x + " y=" + y + " z=" + z); } } - return distanceStyle.computeDistance(thePoint, x, y, z); + return distanceStyle.toAggregationForm(distanceStyle.computeDistance(thePoint, x, y, z)); } @Override @@ -1408,7 +1537,10 @@ class GeoStandardPath extends GeoBasePath { final DistanceStyle distanceStyle, final double x, final double y, final double z) { // Computes the distance along the path to a point on the path where a perpendicular plane // goes through the specified point. - + // First, if this point is outside the endplanes of the segment, return POSITIVE_INFINITY. + if (!isWithinSection(x, y, z)) { + return Double.POSITIVE_INFINITY; + } // (1) Compute normalizedPerpPlane. If degenerate, then there is no such plane, which means // that the point given is insufficient to distinguish between a family of such planes. // This can happen only if the point is one of the "poles", imagining the normalized plane @@ -1452,7 +1584,7 @@ class GeoStandardPath extends GeoBasePath { @Override public double pathDeltaDistance( final DistanceStyle distanceStyle, final double x, final double y, final double z) { - // Returns 2x the pathCenterDistance. Represents the cost of an "excursion" to and + // Represents the cost of an "excursion" to and // from the path. if (!isWithin(x, y, z)) { diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestGeoPath.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestGeoPath.java index f547ee86227..72d86c07b58 100755 --- a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestGeoPath.java +++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/TestGeoPath.java @@ -431,6 +431,52 @@ public class TestGeoPath extends LuceneTestCase { } + @Test + public void testInterpolation2() { + final double lat = 52.5665; + final double lon = 13.3076; + final double[] pathLats = + new double[] { + 52.5355, 52.54, 52.5626, 52.5665, 52.6007, 52.6135, 52.6303, 52.6651, 52.7074 + }; + final double[] pathLons = + new double[] { + 13.3634, 13.3704, 13.3307, 13.3076, 13.2806, 13.2484, 13.2406, 13.241, 13.1926 + }; + + final GeoPoint carPoint = + new GeoPoint(PlanetModel.SPHERE, Math.toRadians(lat), Math.toRadians(lon)); + final GeoPoint[] pathPoints = new GeoPoint[pathLats.length]; + for (int i = 0; i < pathPoints.length; i++) { + pathPoints[i] = + new GeoPoint( + PlanetModel.SPHERE, Math.toRadians(pathLats[i]), Math.toRadians(pathLons[i])); + } + + // Construct a path with no width + final GeoPath thisPath = GeoPathFactory.makeGeoPath(PlanetModel.SPHERE, 0.0, pathPoints); + // Construct a path with a width + final GeoPath legacyPath = GeoPathFactory.makeGeoPath(PlanetModel.SPHERE, 1e-6, pathPoints); + + // Compute the inside distance to the atPoint using zero-width path + final double distance = thisPath.computeNearestDistance(DistanceStyle.ARC, carPoint); + // Compute the inside distance using legacy path + final double legacyDistance = legacyPath.computeNearestDistance(DistanceStyle.ARC, carPoint); + + // Compute the inside distance using the legacy formula + final double oldFormulaDistance = thisPath.computeDistance(DistanceStyle.ARC, carPoint); + // Compute the inside distance using the legacy formula with the legacy shape + final double oldFormulaLegacyDistance = legacyPath.computeDistance(DistanceStyle.ARC, carPoint); + + // These should be about the same + assertEquals(legacyDistance, distance, 1e-12); + + assertEquals(oldFormulaLegacyDistance, oldFormulaDistance, 1e-12); + + // Since the point we picked is actually on the path, this should also be true + assertEquals(oldFormulaDistance, distance, 1e-12); + } + @Test public void testIdenticalPoints() { PlanetModel planetModel = PlanetModel.WGS84;