diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/DistanceStyle.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/DistanceStyle.java index 1dccffba273..44919e33b2c 100644 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/DistanceStyle.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/DistanceStyle.java @@ -78,16 +78,40 @@ public interface DistanceStyle { */ public double computeDistance(final PlanetModel planetModel, final Plane plane, final double x, final double y, final double z, final Membership... bounds); + /** Convert a distance to a form meant for aggregation. + * This is meant to be used in conjunction with aggregateDistances() and fromAggregationForm(). + * Distances should be converted to aggregation form before aggregation is attempted, + * and they should be converted back from aggregation form to yield a final result. + * @param distance is an output of computeDistance(). + * @return the distance, converted to aggregation form. + */ + public default double toAggregationForm(final double distance) { + return distance; + } + /** Aggregate two distances together to produce a "sum". * This is usually just an addition operation, but in the case of squared distances it is more complex. - * @param distance1 is the first distance. - * @param distance2 is the second distance. - * @return the combined distance. + * Distances should be converted to aggregation form before aggregation is attempted, + * and they should be converted back from aggregation form to yield a final result. + * @param distance1 is the first aggregation form distance. + * @param distance2 is the second aggregation form distance. + * @return the combined aggregation form distance. */ public default double aggregateDistances(final double distance1, final double distance2) { return distance1 + distance2; } + /** Convert an aggregation form distance value back to an actual distance. + * This is meant to be used in conjunctiion with toAggregationForm() and aggregateDistances(). + * Distances should be converted to aggregation form before aggregation is attempted, + * and they should be converted back from aggregation form to yield a final result. + * @param aggregateDistance is the aggregate form of the distance. + * @return the combined distance. + */ + public default double fromAggregationForm(final double aggregateDistance) { + return aggregateDistance; + } + // The following methods are used to go from a distance value back to something // that can be used to construct a constrained shape. 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 cde1c49e23b..8025a88a913 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 @@ -223,7 +223,7 @@ class GeoStandardPath extends GeoBasePath { for (PathSegment segment : segments) { double distance = segment.pathDistance(planetModel, distanceStyle, x,y,z); if (distance != Double.POSITIVE_INFINITY) - return distanceStyle.aggregateDistances(currentDistance, distance); + return distanceStyle.fromAggregationForm(distanceStyle.aggregateDistances(currentDistance, distance)); currentDistance = distanceStyle.aggregateDistances(currentDistance, segment.fullPathDistance(distanceStyle)); } @@ -232,7 +232,7 @@ class GeoStandardPath extends GeoBasePath { for (SegmentEndpoint endpoint : endPoints) { double distance = endpoint.pathDistance(distanceStyle, x, y, z); if (distance != Double.POSITIVE_INFINITY) - return distanceStyle.aggregateDistances(currentDistance, distance); + return distanceStyle.fromAggregationForm(distanceStyle.aggregateDistances(currentDistance, distance)); if (segmentIndex < segments.size()) currentDistance = distanceStyle.aggregateDistances(currentDistance, segments.get(segmentIndex++).fullPathDistance(distanceStyle)); } @@ -554,12 +554,12 @@ class GeoStandardPath extends GeoBasePath { *@param x is the point x. *@param y is the point y. *@param z is the point z. - *@return the distance metric. + *@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.computeDistance(this.point, x, y, z); + return distanceStyle.toAggregationForm(distanceStyle.computeDistance(this.point, x, y, z)); } /** Compute external distance. @@ -729,13 +729,13 @@ class GeoStandardPath extends GeoBasePath { /** Compute the full distance along this path segment. *@param distanceStyle is the distance style. - *@return the distance metric. + *@return the distance metric, in aggregation form. */ public double fullPathDistance(final DistanceStyle distanceStyle) { synchronized (fullDistanceCache) { Double dist = fullDistanceCache.get(distanceStyle); if (dist == null) { - dist = new Double(distanceStyle.computeDistance(start, end.x, end.y, end.z)); + dist = new Double(distanceStyle.toAggregationForm(distanceStyle.computeDistance(start, end.x, end.y, end.z))); fullDistanceCache.put(distanceStyle, dist); } return dist.doubleValue(); @@ -772,7 +772,7 @@ class GeoStandardPath extends GeoBasePath { *@param x is the point x. *@param y is the point y. *@param z is the point z. - *@return the distance metric. + *@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) { if (!isWithin(x,y,z)) @@ -785,7 +785,7 @@ class GeoStandardPath extends GeoBasePath { final double perpZ = normalizedConnectingPlane.x * y - normalizedConnectingPlane.y * x; final double magnitude = Math.sqrt(perpX * perpX + perpY * perpY + perpZ * perpZ); if (Math.abs(magnitude) < Vector.MINIMUM_RESOLUTION) - return distanceStyle.computeDistance(start, x,y,z); + return distanceStyle.toAggregationForm(distanceStyle.computeDistance(start, x,y,z)); final double normFactor = 1.0/magnitude; final Plane normalizedPerpPlane = new Plane(perpX * normFactor, perpY * normFactor, perpZ * normFactor, 0.0); @@ -807,7 +807,8 @@ class GeoStandardPath extends GeoBasePath { else throw new RuntimeException("Can't find world intersection for point x="+x+" y="+y+" z="+z); } - return distanceStyle.aggregateDistances(distanceStyle.computeDistance(thePoint, x, y, z), distanceStyle.computeDistance(start, thePoint.x, thePoint.y, thePoint.z)); + return distanceStyle.aggregateDistances(distanceStyle.toAggregationForm(distanceStyle.computeDistance(thePoint, x, y, z)), + distanceStyle.toAggregationForm(distanceStyle.computeDistance(start, thePoint.x, thePoint.y, thePoint.z))); } /** Compute external distance. diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearSquaredDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearSquaredDistance.java index c1800f61803..12ef926c60d 100644 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearSquaredDistance.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearSquaredDistance.java @@ -52,9 +52,13 @@ public class LinearSquaredDistance implements DistanceStyle { } @Override - public double aggregateDistances(final double distance1, final double distance2) { - final double linearDistance = Math.sqrt(distance1) + Math.sqrt(distance2); - return linearDistance * linearDistance; + public double toAggregationForm(final double distance) { + return Math.sqrt(distance); + } + + @Override + public double fromAggregationForm(final double aggregateDistance) { + return aggregateDistance * aggregateDistance; } @Override diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalSquaredDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalSquaredDistance.java index 3a68cc97c9b..25b467c87db 100644 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalSquaredDistance.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalSquaredDistance.java @@ -52,9 +52,13 @@ public class NormalSquaredDistance implements DistanceStyle { } @Override - public double aggregateDistances(final double distance1, final double distance2) { - final double normalDistance = Math.sqrt(distance1) + Math.sqrt(distance2); - return normalDistance * normalDistance; + public double toAggregationForm(final double distance) { + return Math.sqrt(distance); + } + + @Override + public double fromAggregationForm(final double aggregateDistance) { + return aggregateDistance * aggregateDistance; } @Override