You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by kw...@apache.org on 2016/04/19 16:20:35 UTC

lucene-solr:master: LUCENE-7212: Structural changes necessary to support distance-limited bounds.

Repository: lucene-solr
Updated Branches:
  refs/heads/master 02f1dacc3 -> 234229081


LUCENE-7212: Structural changes necessary to support distance-limited bounds.


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/23422908
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/23422908
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/23422908

Branch: refs/heads/master
Commit: 23422908165f62581c271524955af2ab0e6e069f
Parents: 02f1dac
Author: Karl Wright <Da...@gmail.com>
Authored: Tue Apr 19 10:20:00 2016 -0400
Committer: Karl Wright <Da...@gmail.com>
Committed: Tue Apr 19 10:20:00 2016 -0400

----------------------------------------------------------------------
 .../org/apache/lucene/spatial3d/Geo3DUtil.java  |   1 +
 .../lucene/spatial3d/geom/ArcDistance.java      |  15 +++
 .../lucene/spatial3d/geom/DistanceStyle.java    |  28 +++++
 .../spatial3d/geom/GeoBaseDistanceShape.java    |  12 ++
 .../spatial3d/geom/GeoDegeneratePoint.java      |   6 +
 .../lucene/spatial3d/geom/GeoDistance.java      |   1 +
 .../lucene/spatial3d/geom/GeoDistanceShape.java |  12 ++
 .../spatial3d/geom/GeoStandardCircle.java       |   6 +
 .../lucene/spatial3d/geom/GeoStandardPath.java  |   6 +
 .../lucene/spatial3d/geom/LinearDistance.java   |  15 +++
 .../spatial3d/geom/LinearSquaredDistance.java   |  15 +++
 .../lucene/spatial3d/geom/NormalDistance.java   |  15 +++
 .../spatial3d/geom/NormalSquaredDistance.java   |  15 +++
 .../org/apache/lucene/spatial3d/geom/Plane.java | 114 +++++++++++++++++++
 .../apache/lucene/spatial3d/geom/PlaneTest.java |  20 ++++
 15 files changed, 281 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/23422908/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DUtil.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DUtil.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DUtil.java
index f91a6f6..bfda66f 100644
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DUtil.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DUtil.java
@@ -64,4 +64,5 @@ class Geo3DUtil {
       return Math.nextDown((x+1) * DECODE);
     }
   }
+  
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/23422908/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/ArcDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/ArcDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/ArcDistance.java
index bb60be0..25b9c7d 100644
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/ArcDistance.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/ArcDistance.java
@@ -51,6 +51,21 @@ public class ArcDistance implements DistanceStyle {
     return plane.arcDistance(planetModel, x,y,z, bounds);
   }
 
+  @Override
+  public GeoPoint[] findDistancePoints(final PlanetModel planetModel, final double distanceValue, final GeoPoint startPoint, final Plane plane, final Membership... bounds) {
+    return plane.findArcDistancePoints(planetModel, distanceValue, startPoint, bounds);
+  }
+  
+  @Override
+  public double findMinimumArcDistance(final PlanetModel planetModel, final double distanceValue) {
+    return distanceValue;
+  }
+  
+  @Override
+  public double findMaximumArcDistance(final PlanetModel planetModel, final double distanceValue) {
+    return distanceValue;
+  }
+
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/23422908/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/DistanceStyle.java
----------------------------------------------------------------------
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 8c8658d..3657fe9 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,6 +78,34 @@ public interface DistanceStyle {
    */
   public double computeDistance(final PlanetModel planetModel, final Plane plane, final double x, final double y, final double z, final Membership... bounds);
 
+  // The following methods are used to go from a distance value back to something
+  // that can be used to construct a constrained shape.
+  
+  /**  Find a GeoPoint, at a specified distance from a starting point, within the
+   * specified bounds.  The GeoPoint must be in the specified plane.
+   * @param planetModel is the planet model.
+   * @param distanceValue is the distance to set the new point at, measured from point1 and on the way to point2.
+   * @param startPoint is the starting point.
+   * @param plane is the plane that the point must be in.
+   * @param bounds are the constraints on where the point can be found.
+   * @return zero, one, or two points at the proper distance from startPoint.
+   */
+  public GeoPoint[] findDistancePoints(final PlanetModel planetModel, final double distanceValue, final GeoPoint startPoint, final Plane plane, final Membership... bounds);
+  
+  /** Given a distance metric, find the minimum arc distance represented by that distance metric.
+   * @param planetModel is the planet model.
+   * @param distanceValue is the distance metric.
+   * @return the minimum arc distance that that distance value can represent given the planet model.
+   */
+  public double findMinimumArcDistance(final PlanetModel planetModel, final double distanceValue);
+  
+  /** Given a distance metric, find the maximum arc distance represented by the distance metric.
+   * @param planetModel is the planet model.
+   * @param distanceValue is the distance metric.
+   * @return the maximum arc distance that that distance value can represent given the planet model.
+   */
+  public double findMaximumArcDistance(final PlanetModel planetModel, final double distanceValue);
+
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/23422908/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseDistanceShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseDistanceShape.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseDistanceShape.java
index 39dcf96..ec9b6b7 100644
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseDistanceShape.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseDistanceShape.java
@@ -52,5 +52,17 @@ public abstract class GeoBaseDistanceShape extends GeoBaseMembershipShape implem
   /** Called by a {@code computeDistance} method if X/Y/Z is not within this shape. */
   protected abstract double distance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
 
+  @Override
+  public void getDistanceBounds(final Bounds bounds, final DistanceStyle distanceStyle, final double distanceValue) {
+    if (distanceValue == Double.MAX_VALUE) {
+      getBounds(bounds);
+      return;
+    }
+    distanceBounds(bounds, distanceStyle, distanceValue);
+  }
+  
+  /** Called by a {@code getDistanceBounds} method if distanceValue is not Double.MAX_VALUE. */
+  protected abstract void distanceBounds(final Bounds bounds, final DistanceStyle distanceStyle, final double distanceValue);
+
 }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/23422908/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePoint.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePoint.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePoint.java
index aa4732d..9328b4b 100644
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePoint.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePoint.java
@@ -131,5 +131,11 @@ class GeoDegeneratePoint extends GeoPoint implements GeoBBox, GeoCircle {
       return 0.0;
     return Double.MAX_VALUE;
   }
+  
+  @Override
+  public void getDistanceBounds(final Bounds bounds, final DistanceStyle distanceStyle, final double distanceValue) {
+    getBounds(bounds);
+  }
+
 }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/23422908/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistance.java
index d41dd51..cf8fa23 100755
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistance.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistance.java
@@ -56,4 +56,5 @@ public interface GeoDistance extends Membership {
    */
   public double computeDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
 
+ 
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/23422908/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistanceShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistanceShape.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistanceShape.java
index e7b0348..ebd433f 100755
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistanceShape.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistanceShape.java
@@ -24,4 +24,16 @@ package org.apache.lucene.spatial3d.geom;
  */
 public interface GeoDistanceShape extends GeoMembershipShape, GeoDistance {
 
+  /**
+   * Compute a bound based on a provided distance measure.
+   * This method takes an input distance and distance metric and provides bounds on the
+   * shape if reduced to match that distance.  The method is allowed to return
+   * bounds that are larger than the distance would indicate, but never smaller.
+   * @param bounds is the bounds object to update.
+   * @param distanceStyle describes the type of distance metric provided.
+   * @param distanceValue is the distance metric to use.  It is presumed that the distance metric
+   *  was produced with the same distance style as is provided to this method.
+   */
+  public void getDistanceBounds(final Bounds bounds, final DistanceStyle distanceStyle, final double distanceValue);
+
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/23422908/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoStandardCircle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoStandardCircle.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoStandardCircle.java
index 1bc25be..06bef00 100755
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoStandardCircle.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoStandardCircle.java
@@ -107,6 +107,12 @@ class GeoStandardCircle extends GeoBaseCircle {
   }
 
   @Override
+  protected void distanceBounds(final Bounds bounds, final DistanceStyle distanceStyle, final double distanceValue) {
+    // TBD: Compute actual bounds based on distance
+    getBounds(bounds);
+  }
+
+  @Override
   protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
     return distanceStyle.computeDistance(planetModel, circlePlane, x, y, z);
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/23422908/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoStandardPath.java
----------------------------------------------------------------------
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 1546439..312b79e 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
@@ -220,6 +220,12 @@ class GeoStandardPath extends GeoBasePath {
   }
 
   @Override
+  protected void distanceBounds(final Bounds bounds, final DistanceStyle distanceStyle, final double distanceValue) {
+    // TBD: Compute actual bounds based on distance
+    getBounds(bounds);
+  }
+
+  @Override
   protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
     double minDistance = Double.MAX_VALUE;
     for (final SegmentEndpoint endpoint : endPoints) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/23422908/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearDistance.java
index 0c89a16..f301f49 100644
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearDistance.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearDistance.java
@@ -51,6 +51,21 @@ public class LinearDistance implements DistanceStyle {
     return plane.linearDistance(planetModel, x,y,z, bounds);
   }
 
+  @Override
+  public GeoPoint[] findDistancePoints(final PlanetModel planetModel, final double distanceValue, final GeoPoint startPoint, final Plane plane, final Membership... bounds) {
+    throw new IllegalStateException("Reverse mapping not implemented for this distance metric");
+  }
+  
+  @Override
+  public double findMinimumArcDistance(final PlanetModel planetModel, final double distanceValue) {
+    throw new IllegalStateException("Reverse mapping not implemented for this distance metric");
+  }
+  
+  @Override
+  public double findMaximumArcDistance(final PlanetModel planetModel, final double distanceValue) {
+    throw new IllegalStateException("Reverse mapping not implemented for this distance metric");
+  }
+
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/23422908/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearSquaredDistance.java
----------------------------------------------------------------------
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 3fc37da..4b26f8e 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
@@ -51,6 +51,21 @@ public class LinearSquaredDistance implements DistanceStyle {
     return plane.linearDistanceSquared(planetModel, x,y,z, bounds);
   }
 
+  @Override
+  public GeoPoint[] findDistancePoints(final PlanetModel planetModel, final double distanceValue, final GeoPoint startPoint, final Plane plane, final Membership... bounds) {
+    throw new IllegalStateException("Reverse mapping not implemented for this distance metric");
+  }
+  
+  @Override
+  public double findMinimumArcDistance(final PlanetModel planetModel, final double distanceValue) {
+    throw new IllegalStateException("Reverse mapping not implemented for this distance metric");
+  }
+  
+  @Override
+  public double findMaximumArcDistance(final PlanetModel planetModel, final double distanceValue) {
+    throw new IllegalStateException("Reverse mapping not implemented for this distance metric");
+  }
+
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/23422908/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalDistance.java
index 50b2c7f..64fd20b 100644
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalDistance.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalDistance.java
@@ -51,6 +51,21 @@ public class NormalDistance implements DistanceStyle {
     return plane.normalDistance(x,y,z, bounds);
   }
 
+  @Override
+  public GeoPoint[] findDistancePoints(final PlanetModel planetModel, final double distanceValue, final GeoPoint startPoint, final Plane plane, final Membership... bounds) {
+    throw new IllegalStateException("Reverse mapping not implemented for this distance metric");
+  }
+  
+  @Override
+  public double findMinimumArcDistance(final PlanetModel planetModel, final double distanceValue) {
+    throw new IllegalStateException("Reverse mapping not implemented for this distance metric");
+  }
+  
+  @Override
+  public double findMaximumArcDistance(final PlanetModel planetModel, final double distanceValue) {
+    throw new IllegalStateException("Reverse mapping not implemented for this distance metric");
+  }
+
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/23422908/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalSquaredDistance.java
----------------------------------------------------------------------
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 a355d09..428e042 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
@@ -51,6 +51,21 @@ public class NormalSquaredDistance implements DistanceStyle {
     return plane.normalDistanceSquared(x,y,z, bounds);
   }
 
+  @Override
+  public GeoPoint[] findDistancePoints(final PlanetModel planetModel, final double distanceValue, final GeoPoint startPoint, final Plane plane, final Membership... bounds) {
+    throw new IllegalStateException("Reverse mapping not implemented for this distance metric");
+  }
+  
+  @Override
+  public double findMinimumArcDistance(final PlanetModel planetModel, final double distanceValue) {
+    throw new IllegalStateException("Reverse mapping not implemented for this distance metric");
+  }
+  
+  @Override
+  public double findMaximumArcDistance(final PlanetModel planetModel, final double distanceValue) {
+    throw new IllegalStateException("Reverse mapping not implemented for this distance metric");
+  }
+
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/23422908/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Plane.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Plane.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Plane.java
index ace7aa4..f0df49d 100755
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Plane.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Plane.java
@@ -1558,6 +1558,120 @@ public class Plane extends Vector {
   }
 
   /**
+   * Locate a point that is within the specified bounds and on the specified plane, that has an arcDistance as
+   * specified from the startPoint.
+   * @param planetModel is the planet model.
+   * @param arcDistanceValue is the arc distance.
+   * @param startPoint is the starting point.
+   * @param bounds are the bounds.
+   * @return zero, one, or two points.
+   */
+  public GeoPoint[] findArcDistancePoints(final PlanetModel planetModel, final double arcDistanceValue, final GeoPoint startPoint, final Membership... bounds) {
+    if (Math.abs(D) >= MINIMUM_RESOLUTION) {
+      throw new IllegalStateException("Can't find arc distance using plane that doesn't go through origin");
+    }
+    if (!evaluateIsZero(startPoint)) {
+      throw new IllegalArgumentException("Start point is not on plane");
+    }
+    assert Math.abs(x*x + y*y + z*z - 1.0) < MINIMUM_RESOLUTION_SQUARED : "Plane needs to be normalized";
+    
+    // The first step is to rotate coordinates for the point so that the plane lies on the x-y plane.
+    // To acheive this, there will need to be three rotations:
+    // (1) rotate the plane in x-y so that the y axis lies in it.
+    // (2) rotate the plane in x-z so that the plane lies on the x-y plane.
+    // (3) rotate in x-y so that the starting vector points to (1,0,0).
+    
+    // This presumes a normalized plane!!
+    final double azimuthMagnitude = Math.sqrt(this.x * this.x + this.y * this.y);
+    final double cosPlaneAltitude = this.z;
+    final double sinPlaneAltitude = azimuthMagnitude;
+    final double cosPlaneAzimuth = this.x / azimuthMagnitude;
+    final double sinPlaneAzimuth = this.y / azimuthMagnitude;
+    
+    assert Math.abs(sinPlaneAltitude * sinPlaneAltitude + cosPlaneAltitude * cosPlaneAltitude - 1.0) < MINIMUM_RESOLUTION : "Improper sin/cos of altitude: "+(sinPlaneAltitude * sinPlaneAltitude + cosPlaneAltitude * cosPlaneAltitude);
+    assert Math.abs(sinPlaneAzimuth * sinPlaneAzimuth + cosPlaneAzimuth * cosPlaneAzimuth - 1.0) < MINIMUM_RESOLUTION : "Improper sin/cos of azimuth: "+(sinPlaneAzimuth * sinPlaneAzimuth + cosPlaneAzimuth * cosPlaneAzimuth);
+
+    // Coordinate rotation formula:
+    // xT = xS cos T - yS sin T
+    // yT = xS sin T + yS cos T
+    // But we're rotating backwards, so use:
+    // sin (-T) = -sin (T)
+    // cos (-T) = cos (T)
+    
+    // Now, rotate startpoint in x-y
+    final double x0 = startPoint.x;
+    final double y0 = startPoint.y;
+    final double z0 = startPoint.z;
+    
+    final double x1 = x0 * cosPlaneAzimuth + y0 * sinPlaneAzimuth;
+    final double y1 = -x0 * sinPlaneAzimuth + y0 * cosPlaneAzimuth;
+    final double z1 = z0;
+    
+    // Rotate now in x-z
+    final double x2 = x1 * cosPlaneAltitude - z1 * sinPlaneAltitude;
+    final double y2 = y1;
+    final double z2 = +x1 * sinPlaneAltitude + z1 * cosPlaneAltitude;
+    
+    assert Math.abs(z2) < MINIMUM_RESOLUTION : "Rotation should have put startpoint on x-y plane, instead has value "+z2;
+    
+    // Ok, we have the start point on the x-y plane.  To apply the arc distance, we
+    // next need to convert to an angle (in radians).
+    final double startAngle = Math.atan2(y2, x2);
+    
+    // To apply the arc distance, just add to startAngle.
+    final double point1Angle = startAngle + arcDistanceValue;
+    final double point2Angle = startAngle - arcDistanceValue;
+    // Convert each point to x-y
+    final double point1x2 = Math.cos(point1Angle);
+    final double point1y2 = Math.sin(point1Angle);
+    final double point1z2 = 0.0;
+    
+    final double point2x2 = Math.cos(point2Angle);
+    final double point2y2 = Math.sin(point2Angle);
+    final double point2z2 = 0.0;
+    
+    // Now, do the reverse rotations for both points
+    // Altitude...
+    final double point1x1 = point1x2 * cosPlaneAltitude + point1z2 * sinPlaneAltitude;
+    final double point1y1 = point1y2;
+    final double point1z1 = -point1x2 * sinPlaneAltitude + point1z2 * cosPlaneAltitude;
+    
+    final double point2x1 = point2x2 * cosPlaneAltitude + point2z2 * sinPlaneAltitude;
+    final double point2y1 = point2y2;
+    final double point2z1 = -point2x2 * sinPlaneAltitude + point2z2 * cosPlaneAltitude;
+
+    // Azimuth...
+    final double point1x0 = point1x1 * cosPlaneAzimuth - point1y1 * sinPlaneAzimuth;
+    final double point1y0 = point1x1 * sinPlaneAzimuth + point1y1 * cosPlaneAzimuth;
+    final double point1z0 = point1z1;
+
+    final double point2x0 = point2x1 * cosPlaneAzimuth - point2y1 * sinPlaneAzimuth;
+    final double point2y0 = point2x1 * sinPlaneAzimuth + point2y1 * cosPlaneAzimuth;
+    final double point2z0 = point2z1;
+
+    final GeoPoint point1 = planetModel.createSurfacePoint(point1x0, point1y0, point1z0);
+    final GeoPoint point2 = planetModel.createSurfacePoint(point2x0, point2y0, point2z0);
+    
+    // Figure out what to return
+    boolean isPoint1Inside = meetsAllBounds(point1, bounds);
+    boolean isPoint2Inside = meetsAllBounds(point2, bounds);
+    
+    if (isPoint1Inside) {
+      if (isPoint2Inside) {
+        return new GeoPoint[]{point1, point2};
+      } else {
+        return new GeoPoint[]{point1};
+      }
+    } else {
+      if (isPoint2Inside) {
+        return new GeoPoint[]{point2};
+      } else {
+        return new GeoPoint[0];
+      }
+    }
+  }
+  
+  /**
    * Check if a vector meets the provided bounds.
    * @param p is the vector.
    * @param bounds are the bounds.

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/23422908/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/PlaneTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/PlaneTest.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/PlaneTest.java
index 91bd0c3..5f64bdf 100644
--- a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/PlaneTest.java
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/PlaneTest.java
@@ -20,6 +20,7 @@ import org.junit.Test;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
 
 /**
  * Test basic plane functionality.
@@ -60,5 +61,24 @@ public class PlaneTest {
       assertTrue(p.evaluateIsZero(point));
     }
   }
+  
+  @Test
+  public void testFindArcPoints() {
+    // Create two points
+    final GeoPoint p1 = new GeoPoint(PlanetModel.WGS84, 0.123, -0.456);
+    final GeoPoint p2 = new GeoPoint(PlanetModel.WGS84, -0.368, 0.888);
+    // Create a plane that links them.
+    final Plane plane = new Plane(p1, p2);
+    // Now, use that plane to find points that are a certain distance from the original
+    final GeoPoint[] newPoints = plane.findArcDistancePoints(PlanetModel.WGS84, 0.20, p1);
+    assertTrue(newPoints.length == 2);
+    assertTrue(plane.evaluateIsZero(newPoints[0]));
+    assertTrue(plane.evaluateIsZero(newPoints[1]));
+    assertTrue(PlanetModel.WGS84.pointOnSurface(newPoints[0]));
+    assertTrue(PlanetModel.WGS84.pointOnSurface(newPoints[1]));
+    assertEquals(0.20, p1.arcDistance(newPoints[0]), 1e-6);
+    assertEquals(0.20, p1.arcDistance(newPoints[1]), 1e-6);
+  }
+  
 }