You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ds...@apache.org on 2015/07/01 04:16:56 UTC

svn commit: r1688546 [1/2] - in /lucene/dev/branches/branch_5x: ./ lucene/ lucene/spatial/ lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/ lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/

Author: dsmiley
Date: Wed Jul  1 02:16:55 2015
New Revision: 1688546

URL: http://svn.apache.org/r1688546
Log:
LUCENE-6578: Geo3D: compute the distance from a point to a shape.

Added:
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/ArcDistance.java
      - copied unchanged from r1688545, lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/ArcDistance.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/BasePlanetObject.java
      - copied unchanged from r1688545, lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/BasePlanetObject.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/DistanceStyle.java
      - copied, changed from r1688545, lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/DistanceStyle.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoBaseDistanceShape.java
      - copied unchanged from r1688545, lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoBaseDistanceShape.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoBaseMembershipShape.java
      - copied unchanged from r1688545, lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoBaseMembershipShape.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoOutsideDistance.java
      - copied, changed from r1688545, lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoOutsideDistance.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/LinearDistance.java
      - copied unchanged from r1688545, lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/LinearDistance.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/LinearSquaredDistance.java
      - copied unchanged from r1688545, lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/LinearSquaredDistance.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/NormalDistance.java
      - copied unchanged from r1688545, lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/NormalDistance.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/NormalSquaredDistance.java
      - copied unchanged from r1688545, lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/NormalSquaredDistance.java
Removed:
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoBaseExtendedShape.java
Modified:
    lucene/dev/branches/branch_5x/   (props changed)
    lucene/dev/branches/branch_5x/lucene/   (props changed)
    lucene/dev/branches/branch_5x/lucene/CHANGES.txt   (contents, props changed)
    lucene/dev/branches/branch_5x/lucene/spatial/   (props changed)
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoBaseBBox.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoBaseShape.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoCircle.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoCompositeMembershipShape.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoConvexPolygon.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateHorizontalLine.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateLatitudeZone.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateLongitudeSlice.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegeneratePoint.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateVerticalLine.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDistance.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoLatitudeZone.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoLongitudeSlice.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoMembershipShape.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoNorthLatitudeZone.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoNorthRectangle.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPath.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPoint.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoRectangle.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoShape.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoSouthLatitudeZone.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoSouthRectangle.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideDegenerateHorizontalLine.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideLongitudeSlice.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideNorthRectangle.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideRectangle.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideSouthRectangle.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWorld.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Membership.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Plane.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/SidedPlane.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Vector.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoBBoxTest.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoCircleTest.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoConvexPolygonTest.java
    lucene/dev/branches/branch_5x/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoPathTest.java

Modified: lucene/dev/branches/branch_5x/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/CHANGES.txt?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/CHANGES.txt (original)
+++ lucene/dev/branches/branch_5x/lucene/CHANGES.txt Wed Jul  1 02:16:55 2015
@@ -70,6 +70,10 @@ New Features
   near-real-time or non-NRT reader.  (Boaz Leskes, Robert Muir, Mike
   McCandless)
 
+* LUCENE-6578: Geo3D can now compute the distance from a point to a shape, both
+  inner distance and to an outside edge. Multiple distance algorithms are
+  available.  (Karl Wright, David Smiley)
+
 API Changes
 
 * LUCENE-6508: Simplify Lock api, there is now just 

Copied: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/DistanceStyle.java (from r1688545, lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/DistanceStyle.java)
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/DistanceStyle.java?p2=lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/DistanceStyle.java&p1=lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/DistanceStyle.java&r1=1688545&r2=1688546&rev=1688546&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/DistanceStyle.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/DistanceStyle.java Wed Jul  1 02:16:55 2015
@@ -38,9 +38,7 @@ public interface DistanceStyle {
    * @param point2 Final point
    * @return the distance
    */
-  public default double computeDistance(final GeoPoint point1, final GeoPoint point2) {
-    return computeDistance(point1, point2.x, point2.y, point2.z);
-  }
+  public double computeDistance(final GeoPoint point1, final GeoPoint point2);
   
   /** Compute the distance from a point to another point.
    * @param point1 Starting point
@@ -58,10 +56,8 @@ public interface DistanceStyle {
    * @param bounds are the plane bounds
    * @return the distance
    */
-  public default double computeDistance(final PlanetModel planetModel, final Plane plane, final GeoPoint point,
-                                        final Membership... bounds) {
-    return computeDistance(planetModel, plane, point.x, point.y, point.z, bounds);
-  }
+  public double computeDistance(final PlanetModel planetModel, final Plane plane, final GeoPoint point,
+                                        final Membership... bounds);
   
   /** Compute the distance from a plane to a point.
    * @param planetModel The planet model

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoBaseBBox.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoBaseBBox.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoBaseBBox.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoBaseBBox.java Wed Jul  1 02:16:55 2015
@@ -23,14 +23,11 @@ package org.apache.lucene.spatial.spatia
  *
  * @lucene.internal
  */
-public abstract class GeoBaseBBox extends GeoBaseShape implements GeoBBox {
+public abstract class GeoBaseBBox extends GeoBaseMembershipShape implements GeoBBox {
 
   public GeoBaseBBox(final PlanetModel planetModel) {
     super(planetModel);
   }
-  
-  @Override
-  public abstract boolean isWithin(final Vector point);
 
   protected final static int ALL_INSIDE = 0;
   protected final static int SOME_INSIDE = 1;
@@ -58,15 +55,6 @@ public abstract class GeoBaseBBox extend
       return NONE_INSIDE;
     return SOME_INSIDE;
   }
-  
-  @Override
-  public int hashCode() {
-    return super.hashCode();
-  }
-  
-  @Override
-  public boolean equals(final Object o) {
-    return super.equals(o);
-  }
+
 }
 

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoBaseShape.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoBaseShape.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoBaseShape.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoBaseShape.java Wed Jul  1 02:16:55 2015
@@ -18,30 +18,29 @@ package org.apache.lucene.spatial.spatia
  */
 
 /**
- * All bounding box shapes can derive from this base class, which furnishes
- * some common code
+ * Base extended shape object.
  *
  * @lucene.internal
  */
-public abstract class GeoBaseShape {
+public abstract class GeoBaseShape extends BasePlanetObject implements GeoShape {
 
-  protected final PlanetModel planetModel;
-  
   public GeoBaseShape(final PlanetModel planetModel) {
-    this.planetModel = planetModel;
+    super(planetModel);
   }
-  
-  @Override
-  public int hashCode() {
-    return planetModel.hashCode();
-  }
-  
+
   @Override
-  public boolean equals(final Object o) {
-    if (!(o instanceof GeoBaseShape))
-      return false;
-    return planetModel.equals(((GeoBaseShape)o).planetModel);
+  public Bounds getBounds(Bounds bounds) {
+    if (bounds == null)
+      bounds = new Bounds();
+    if (isWithin(planetModel.NORTH_POLE)) {
+      bounds.noTopLatitudeBound().noLongitudeBound();
+    }
+    if (isWithin(planetModel.SOUTH_POLE)) {
+      bounds.noBottomLatitudeBound().noLongitudeBound();
+    }
+    return bounds;
   }
+
 }
 
 

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoCircle.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoCircle.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoCircle.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoCircle.java Wed Jul  1 02:16:55 2015
@@ -22,7 +22,7 @@ package org.apache.lucene.spatial.spatia
  *
  * @lucene.experimental
  */
-public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape, GeoSizeable {
+public class GeoCircle extends GeoBaseDistanceShape implements GeoSizeable {
   public final GeoPoint center;
   public final double cutoffAngle;
   public final SidedPlane circlePlane;
@@ -81,124 +81,19 @@ public class GeoCircle extends GeoBaseEx
     return cutoffAngle;
   }
 
-  /**
-   * Returns the center of a circle into which the area will be inscribed.
-   *
-   * @return the center.
-   */
   @Override
   public GeoPoint getCenter() {
     return center;
   }
 
-  /**
-   * Compute an estimate of "distance" to the GeoPoint.
-   * A return value of Double.MAX_VALUE should be returned for
-   * points outside of the shape.
-   */
   @Override
-  public double computeNormalDistance(final GeoPoint point) {
-    if (!isWithin(point))
-      return Double.MAX_VALUE;
-    return this.center.normalDistance(point);
+  protected double distance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    return distanceStyle.computeDistance(this.center, x, y, z);
   }
 
-  /**
-   * Compute an estimate of "distance" to the GeoPoint.
-   * A return value of Double.MAX_VALUE should be returned for
-   * points outside of the shape.
-   */
   @Override
-  public double computeNormalDistance(final double x, final double y, final double z) {
-    if (!isWithin(x,y,z))
-      return Double.MAX_VALUE;
-    return this.center.normalDistance(x, y, z);
-  }
-
-  /**
-   * Compute a squared estimate of the "distance" to the
-   * GeoPoint.  Double.MAX_VALUE indicates a point outside of the
-   * shape.
-   */
-  @Override
-  public double computeSquaredNormalDistance(final GeoPoint point) {
-    if (!isWithin(point))
-      return Double.MAX_VALUE;
-    return this.center.normalDistanceSquared(point);
-  }
-
-  /**
-   * Compute a squared estimate of the "distance" to the
-   * GeoPoint.  Double.MAX_VALUE indicates a point outside of the
-   * shape.
-   */
-  @Override
-  public double computeSquaredNormalDistance(final double x, final double y, final double z) {
-    if (!isWithin(x,y,z))
-      return Double.MAX_VALUE;
-    return this.center.normalDistanceSquared(x, y, z);
-  }
-
-  /**
-   * Compute a linear distance to the vector.
-   * return Double.MAX_VALUE for points outside the shape.
-   */
-  @Override
-  public double computeLinearDistance(final GeoPoint point) {
-    if (!isWithin(point))
-      return Double.MAX_VALUE;
-    return this.center.linearDistance(point);
-  }
-
-  /**
-   * Compute a linear distance to the vector.
-   * return Double.MAX_VALUE for points outside the shape.
-   */
-  @Override
-  public double computeLinearDistance(final double x, final double y, final double z) {
-    if (!isWithin(x,y,z))
-      return Double.MAX_VALUE;
-    return this.center.linearDistance(x, y, z);
-  }
-
-  /**
-   * Compute a squared linear distance to the vector.
-   */
-  @Override
-  public double computeSquaredLinearDistance(final GeoPoint point) {
-    if (!isWithin(point))
-      return Double.MAX_VALUE;
-    return this.center.linearDistanceSquared(point);
-  }
-
-  /**
-   * Compute a squared linear distance to the vector.
-   */
-  @Override
-  public double computeSquaredLinearDistance(final double x, final double y, final double z) {
-    if (!isWithin(x,y,z))
-      return Double.MAX_VALUE;
-    return this.center.linearDistanceSquared(x, y, z);
-  }
-
-  /**
-   * Compute a true, accurate, great-circle distance.
-   * Double.MAX_VALUE indicates a point is outside of the shape.
-   */
-  @Override
-  public double computeArcDistance(final GeoPoint point) {
-    if (!isWithin(point))
-      return Double.MAX_VALUE;
-    return this.center.arcDistance(point);
-  }
-
-  @Override
-  public boolean isWithin(final Vector point) {
-    if (circlePlane == null) {
-      return true;
-    }
-    // Fastest way of determining membership
-    return circlePlane.isWithin(point);
+  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    return distanceStyle.computeDistance(planetModel, circlePlane, x, y, z);
   }
 
   @Override
@@ -223,15 +118,6 @@ public class GeoCircle extends GeoBaseEx
     return circlePlane.intersects(planetModel, p, notablePoints, circlePoints, bounds);
   }
 
-  /**
-   * Compute longitude/latitude bounds for the shape.
-   *
-   * @param bounds is the optional input bounds object.  If this is null,
-   *               a bounds object will be created.  Otherwise, the input object will be modified.
-   * @return a Bounds object describing the shape's bounds.  If the bounds cannot
-   * be computed, then return a Bounds object with noLongitudeBound,
-   * noTopLatitudeBound, and noBottomLatitudeBound.
-   */
   @Override
   public Bounds getBounds(Bounds bounds) {
     bounds = super.getBounds(bounds);

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoCompositeMembershipShape.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoCompositeMembershipShape.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoCompositeMembershipShape.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoCompositeMembershipShape.java Wed Jul  1 02:16:55 2015
@@ -40,14 +40,7 @@ public class GeoCompositeMembershipShape
 
   @Override
   public boolean isWithin(final Vector point) {
-    //System.err.println("Checking whether point "+point+" is within Composite");
-    for (GeoMembershipShape shape : shapes) {
-      if (shape.isWithin(point)) {
-        //System.err.println(" Point is within "+shape);
-        return true;
-      }
-    }
-    return false;
+    return isWithin(point.x, point.y, point.z);
   }
 
   @Override
@@ -73,15 +66,6 @@ public class GeoCompositeMembershipShape
     return false;
   }
 
-  /**
-   * Compute longitude/latitude bounds for the shape.
-   *
-   * @param bounds is the optional input bounds object.  If this is null,
-   *               a bounds object will be created.  Otherwise, the input object will be modified.
-   * @return a Bounds object describing the shape's bounds.  If the bounds cannot
-   * be computed, then return a Bounds object with noLongitudeBound,
-   * noTopLatitudeBound, and noBottomLatitudeBound.
-   */
   @Override
   public Bounds getBounds(Bounds bounds) {
     if (bounds == null)
@@ -93,23 +77,36 @@ public class GeoCompositeMembershipShape
   }
 
   @Override
+  public double computeOutsideDistance(final DistanceStyle distanceStyle, final GeoPoint point) {
+    return computeOutsideDistance(distanceStyle, point.x, point.y, point.z);
+  }
+
+  @Override
+  public double computeOutsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    if (isWithin(x,y,z))
+      return 0.0;
+    double distance = Double.MAX_VALUE;
+    for (GeoMembershipShape shape : shapes) {
+      final double normalDistance = shape.computeOutsideDistance(distanceStyle, x, y, z);
+      if (normalDistance < distance) {
+        distance = normalDistance;
+      }
+    }
+    return distance;
+  }
+
+  @Override
   public boolean equals(Object o) {
     if (!(o instanceof GeoCompositeMembershipShape))
       return false;
     GeoCompositeMembershipShape other = (GeoCompositeMembershipShape) o;
-    if (other.shapes.size() != shapes.size())
-      return false;
 
-    for (int i = 0; i < shapes.size(); i++) {
-      if (!other.shapes.get(i).equals(shapes.get(i)))
-        return false;
-    }
-    return true;
+    return super.equals(o) && shapes.equals(other.shapes);
   }
 
   @Override
   public int hashCode() {
-    return shapes.hashCode();//TODO cache
+    return super.hashCode() * 31 + shapes.hashCode();//TODO cache
   }
 
   @Override

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoConvexPolygon.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoConvexPolygon.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoConvexPolygon.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoConvexPolygon.java Wed Jul  1 02:16:55 2015
@@ -29,7 +29,7 @@ import java.util.List;
  *
  * @lucene.experimental
  */
-public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembershipShape {
+public class GeoConvexPolygon extends GeoBaseMembershipShape {
   protected final List<GeoPoint> points;
   protected final BitSet isInternalEdges;
 
@@ -152,15 +152,6 @@ public class GeoConvexPolygon extends Ge
   }
 
   @Override
-  public boolean isWithin(final Vector point) {
-    for (final SidedPlane edge : edges) {
-      if (!edge.isWithin(point))
-        return false;
-    }
-    return true;
-  }
-
-  @Override
   public boolean isWithin(final double x, final double y, final double z) {
     for (final SidedPlane edge : edges) {
       if (!edge.isWithin(x, y, z))
@@ -201,15 +192,6 @@ public class GeoConvexPolygon extends Ge
     return false;
   }
 
-  /**
-   * Compute longitude/latitude bounds for the shape.
-   *
-   * @param bounds is the optional input bounds object.  If this is null,
-   *               a bounds object will be created.  Otherwise, the input object will be modified.
-   * @return a Bounds object describing the shape's bounds.  If the bounds cannot
-   * be computed, then return a Bounds object with noLongitudeBound,
-   * noTopLatitudeBound, and noBottomLatitudeBound.
-   */
   @Override
   public Bounds getBounds(Bounds bounds) {
     bounds = super.getBounds(bounds);
@@ -241,6 +223,32 @@ public class GeoConvexPolygon extends Ge
   }
 
   @Override
+  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    double minimumDistance = Double.MAX_VALUE;
+    for (final GeoPoint edgePoint : points) {
+      final double newDist = distanceStyle.computeDistance(edgePoint, x,y,z);
+      if (newDist < minimumDistance) {
+        minimumDistance = newDist;
+      }
+    }
+    for (int edgeIndex = 0; edgeIndex < edges.length; edgeIndex++) {
+      final Plane edgePlane = edges[edgeIndex];
+      final Membership[] membershipBounds = new Membership[edges.length - 1];
+      int count = 0;
+      for (int otherIndex = 0; otherIndex < edges.length; otherIndex++) {
+        if (otherIndex != edgeIndex) {
+          membershipBounds[count++] = edges[otherIndex];
+        }
+      }
+      final double newDist = distanceStyle.computeDistance(planetModel, edgePlane, x, y, z, membershipBounds);
+      if (newDist < minimumDistance) {
+        minimumDistance = newDist;
+      }
+    }
+    return minimumDistance;
+  }
+
+  @Override
   public boolean equals(Object o) {
     if (!(o instanceof GeoConvexPolygon))
       return false;

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateHorizontalLine.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateHorizontalLine.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateHorizontalLine.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateHorizontalLine.java Wed Jul  1 02:16:55 2015
@@ -112,13 +112,6 @@ public class GeoDegenerateHorizontalLine
   }
 
   @Override
-  public boolean isWithin(final Vector point) {
-    return plane.evaluateIsZero(point) &&
-        leftPlane.isWithin(point) &&
-        rightPlane.isWithin(point);
-  }
-
-  @Override
   public boolean isWithin(final double x, final double y, final double z) {
     return plane.evaluateIsZero(x, y, z) &&
         leftPlane.isWithin(x, y, z) &&
@@ -132,11 +125,6 @@ public class GeoDegenerateHorizontalLine
     return Math.max(topAngle, bottomAngle);
   }
 
-  /**
-   * Returns the center of a circle into which the area will be inscribed.
-   *
-   * @return the center.
-   */
   @Override
   public GeoPoint getCenter() {
     return centerPoint;
@@ -152,15 +140,6 @@ public class GeoDegenerateHorizontalLine
     return p.intersects(planetModel, plane, notablePoints, planePoints, bounds, leftPlane, rightPlane);
   }
 
-  /**
-   * Compute longitude/latitude bounds for the shape.
-   *
-   * @param bounds is the optional input bounds object.  If this is null,
-   *               a bounds object will be created.  Otherwise, the input object will be modified.
-   * @return a Bounds object describing the shape's bounds.  If the bounds cannot
-   * be computed, then return a Bounds object with noLongitudeBound,
-   * noTopLatitudeBound, and noBottomLatitudeBound.
-   */
   @Override
   public Bounds getBounds(Bounds bounds) {
     if (bounds == null)
@@ -187,6 +166,18 @@ public class GeoDegenerateHorizontalLine
   }
 
   @Override
+  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    final double distance = distanceStyle.computeDistance(planetModel, plane, x,y,z, leftPlane, rightPlane);
+    
+    final double LHCDistance = distanceStyle.computeDistance(LHC, x,y,z);
+    final double RHCDistance = distanceStyle.computeDistance(RHC, x,y,z);
+    
+    return Math.min(
+      distance,
+      Math.min(LHCDistance, RHCDistance));
+  }
+
+  @Override
   public boolean equals(Object o) {
     if (!(o instanceof GeoDegenerateHorizontalLine))
       return false;

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateLatitudeZone.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateLatitudeZone.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateLatitudeZone.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateLatitudeZone.java Wed Jul  1 02:16:55 2015
@@ -52,11 +52,6 @@ public class GeoDegenerateLatitudeZone e
   }
 
   @Override
-  public boolean isWithin(final Vector point) {
-    return Math.abs(point.z - this.sinLatitude) < 1e-10;
-  }
-
-  @Override
   public boolean isWithin(final double x, final double y, final double z) {
     return Math.abs(z - this.sinLatitude) < 1e-10;
   }
@@ -66,11 +61,6 @@ public class GeoDegenerateLatitudeZone e
     return Math.PI;
   }
 
-  /**
-   * Returns the center of a circle into which the area will be inscribed.
-   *
-   * @return the center.
-   */
   @Override
   public GeoPoint getCenter() {
     // Totally arbitrary
@@ -122,6 +112,11 @@ public class GeoDegenerateLatitudeZone e
   }
 
   @Override
+  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    return distanceStyle.computeDistance(planetModel, plane, x,y,z);
+  }
+
+  @Override
   public boolean equals(Object o) {
     if (!(o instanceof GeoDegenerateLatitudeZone))
       return false;

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateLongitudeSlice.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateLongitudeSlice.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateLongitudeSlice.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateLongitudeSlice.java Wed Jul  1 02:16:55 2015
@@ -69,12 +69,6 @@ public class GeoDegenerateLongitudeSlice
   }
 
   @Override
-  public boolean isWithin(final Vector point) {
-    return plane.evaluateIsZero(point) &&
-        boundingPlane.isWithin(point);
-  }
-
-  @Override
   public boolean isWithin(final double x, final double y, final double z) {
     return plane.evaluateIsZero(x, y, z) &&
         boundingPlane.isWithin(x, y, z);
@@ -85,11 +79,6 @@ public class GeoDegenerateLongitudeSlice
     return Math.PI * 0.5;
   }
 
-  /**
-   * Returns the center of a circle into which the area will be inscribed.
-   *
-   * @return the center.
-   */
   @Override
   public GeoPoint getCenter() {
     return interiorPoint;
@@ -105,15 +94,6 @@ public class GeoDegenerateLongitudeSlice
     return p.intersects(planetModel, plane, notablePoints, planePoints, bounds, boundingPlane);
   }
 
-  /**
-   * Compute longitude/latitude bounds for the shape.
-   *
-   * @param bounds is the optional input bounds object.  If this is null,
-   *               a bounds object will be created.  Otherwise, the input object will be modified.
-   * @return a Bounds object describing the shape's bounds.  If the bounds cannot
-   * be computed, then return a Bounds object with noLongitudeBound,
-   * noTopLatitudeBound, and noBottomLatitudeBound.
-   */
   @Override
   public Bounds getBounds(Bounds bounds) {
     if (bounds == null)
@@ -136,6 +116,18 @@ public class GeoDegenerateLongitudeSlice
   }
 
   @Override
+  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    final double distance = distanceStyle.computeDistance(planetModel, plane, x,y,z, boundingPlane);
+    
+    final double northDistance = distanceStyle.computeDistance(planetModel.NORTH_POLE, x,y,z);
+    final double southDistance = distanceStyle.computeDistance(planetModel.SOUTH_POLE, x,y,z);
+    
+    return Math.min(
+      distance,
+      Math.min(northDistance, southDistance));
+  }
+
+  @Override
   public boolean equals(Object o) {
     if (!(o instanceof GeoDegenerateLongitudeSlice))
       return false;

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegeneratePoint.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegeneratePoint.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegeneratePoint.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegeneratePoint.java Wed Jul  1 02:16:55 2015
@@ -37,12 +37,6 @@ public class GeoDegeneratePoint extends
     this.edgePoints = new GeoPoint[]{this};
   }
 
-  /**
-   * Expand box by specified angle.
-   *
-   * @param angle is the angle amount to expand the GeoBBox by.
-   * @return a new GeoBBox.
-   */
   @Override
   public GeoBBox expand(final double angle) {
     final double newTopLat = latitude + angle;
@@ -52,26 +46,11 @@ public class GeoDegeneratePoint extends
     return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
   }
 
-  /**
-   * Return a sample point that is on the edge of the shape.
-   *
-   * @return an interior point.
-   */
   @Override
   public GeoPoint[] getEdgePoints() {
     return edgePoints;
   }
 
-  /**
-   * Assess whether a plane, within the provided bounds, intersects
-   * with the shape.
-   *
-   * @param plane  is the plane to assess for intersection with the shape's edges or
-   *               bounding curves.
-   * @param bounds are a set of bounds that define an area that an
-   *               intersection must be within in order to qualify (provided by a GeoArea).
-   * @return true if there's such an intersection, false if not.
-   */
   @Override
   public boolean intersects(final Plane plane, final GeoPoint[] notablePoints, final Membership... bounds) {
     // If not on the plane, no intersection
@@ -85,15 +64,6 @@ public class GeoDegeneratePoint extends
     return true;
   }
 
-  /**
-   * Compute longitude/latitude bounds for the shape.
-   *
-   * @param bounds is the optional input bounds object.  If this is null,
-   *               a bounds object will be created.  Otherwise, the input object will be modified.
-   * @return a Bounds object describing the shape's bounds.  If the bounds cannot
-   * be computed, then return a Bounds object with noLongitudeBound,
-   * noTopLatitudeBound, and noBottomLatitudeBound.
-   */
   @Override
   public Bounds getBounds(Bounds bounds) {
     if (bounds == null)
@@ -102,9 +72,16 @@ public class GeoDegeneratePoint extends
     return bounds;
   }
 
-  /**
-   * Equals
-   */
+  @Override
+  public double computeOutsideDistance(final DistanceStyle distanceStyle, final GeoPoint point) {
+    return distanceStyle.computeDistance(this, point);
+  }
+
+  @Override
+  public double computeOutsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    return distanceStyle.computeDistance(this, x,y,z);
+  }
+
   @Override
   public boolean equals(Object o) {
     if (!(o instanceof GeoDegeneratePoint))
@@ -128,61 +105,26 @@ public class GeoDegeneratePoint extends
     return "GeoDegeneratePoint: {planetmodel="+planetModel+", lat=" + latitude + "(" + latitude * 180.0 / Math.PI + "), lon=" + longitude + "(" + longitude * 180.0 / Math.PI + ")}";
   }
 
-  /**
-   * Check if a point is within this shape.
-   *
-   * @param point is the point to check.
-   * @return true if the point is within this shape
-   */
   @Override
   public boolean isWithin(final Vector point) {
     return isWithin(point.x, point.y, point.z);
   }
 
-  /**
-   * Check if a point is within this shape.
-   *
-   * @param x is x coordinate of point to check.
-   * @param y is y coordinate of point to check.
-   * @param z is z coordinate of point to check.
-   * @return true if the point is within this shape
-   */
   @Override
   public boolean isWithin(final double x, final double y, final double z) {
     return x == this.x && y == this.y && z == this.z;
   }
 
-  /**
-   * Returns the radius of a circle into which the GeoSizeable area can
-   * be inscribed.
-   *
-   * @return the radius.
-   */
   @Override
   public double getRadius() {
     return 0.0;
   }
 
-  /**
-   * Returns the center of a circle into which the area will be inscribed.
-   *
-   * @return the center.
-   */
   @Override
   public GeoPoint getCenter() {
     return this;
   }
 
-  /**
-   * Find the spatial relationship between a shape and the current geo area.
-   * Note: return value is how the GeoShape relates to the GeoArea, not the
-   * other way around. For example, if this GeoArea is entirely within the
-   * shape, then CONTAINS should be returned.  If the shape is entirely enclosed
-   * by this GeoArea, then WITHIN should be returned.
-   *
-   * @param shape is the shape to consider.
-   * @return the relationship, from the perspective of the shape.
-   */
   @Override
   public int getRelationship(final GeoShape shape) {
     if (shape.isWithin(this)) {

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateVerticalLine.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateVerticalLine.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateVerticalLine.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDegenerateVerticalLine.java Wed Jul  1 02:16:55 2015
@@ -103,14 +103,6 @@ public class GeoDegenerateVerticalLine e
   }
 
   @Override
-  public boolean isWithin(final Vector point) {
-    return plane.evaluateIsZero(point) &&
-        boundingPlane.isWithin(point) &&
-        topPlane.isWithin(point) &&
-        bottomPlane.isWithin(point);
-  }
-
-  @Override
   public boolean isWithin(final double x, final double y, final double z) {
     return plane.evaluateIsZero(x, y, z) &&
         boundingPlane.isWithin(x, y, z) &&
@@ -128,11 +120,6 @@ public class GeoDegenerateVerticalLine e
     return Math.max(topAngle, bottomAngle);
   }
 
-  /**
-   * Returns the center of a circle into which the area will be inscribed.
-   *
-   * @return the center.
-   */
   @Override
   public GeoPoint getCenter() {
     return centerPoint;
@@ -148,15 +135,6 @@ public class GeoDegenerateVerticalLine e
     return p.intersects(planetModel, plane, notablePoints, planePoints, bounds, boundingPlane, topPlane, bottomPlane);
   }
 
-  /**
-   * Compute longitude/latitude bounds for the shape.
-   *
-   * @param bounds is the optional input bounds object.  If this is null,
-   *               a bounds object will be created.  Otherwise, the input object will be modified.
-   * @return a Bounds object describing the shape's bounds.  If the bounds cannot
-   * be computed, then return a Bounds object with noLongitudeBound,
-   * noTopLatitudeBound, and noBottomLatitudeBound.
-   */
   @Override
   public Bounds getBounds(Bounds bounds) {
     if (bounds == null)
@@ -184,6 +162,18 @@ public class GeoDegenerateVerticalLine e
   }
 
   @Override
+  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    final double distance = distanceStyle.computeDistance(planetModel, plane, x,y,z, topPlane, bottomPlane, boundingPlane);
+    
+    final double UHCDistance = distanceStyle.computeDistance(UHC, x,y,z);
+    final double LHCDistance = distanceStyle.computeDistance(LHC, x,y,z);
+    
+    return Math.min(
+      distance,
+      Math.min(UHCDistance, LHCDistance));
+  }
+
+  @Override
   public boolean equals(Object o) {
     if (!(o instanceof GeoDegenerateVerticalLine))
       return false;

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDistance.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDistance.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDistance.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoDistance.java Wed Jul  1 02:16:55 2015
@@ -18,136 +18,41 @@ package org.apache.lucene.spatial.spatia
  */
 
 /**
- * Generic geo-distance-capable shape class description.  An implementer
- * of this interface is capable of computing the described "distance" values,
+ * An implementer of this interface is capable of computing the described "distance" values,
  * which are meant to provide both actual distance values, as well as
  * distance estimates that can be computed more cheaply.
  *
  * @lucene.experimental
  */
 public interface GeoDistance extends Membership {
-  /**
-   * Compute this shape's normal "distance" to the GeoPoint.
-   * A return value of Double.MAX_VALUE should be returned for
-   * points outside of the shape.
-   *
-   * @param point is the point to compute the distance to.
-   * @return the normal distance, defined as the perpendicular distance from
-   * from the point to one of the shape's bounding plane.  Normal
-   * distances can therefore typically only go up to PI/2, except
-   * when they represent the sum of a sequence of normal distances.
-   */
-  public double computeNormalDistance(GeoPoint point);
-
-  /**
-   * Compute this shape's normal "distance" to the GeoPoint.
-   * A return value of Double.MAX_VALUE should be returned for
-   * points outside of the shape.
-   *
-   * @param x is the point's unit x coordinate (using U.S. convention).
-   * @param y is the point's unit y coordinate (using U.S. convention).
-   * @param z is the point's unit z coordinate (using U.S. convention).
-   * @return the normal distance, defined as the perpendicular distance from
-   * from the point to one of the shape's bounding plane.  Normal
-   * distances can therefore typically only go up to PI/2, except
-   * when they represent the sum of a sequence of normal distances.
-   */
-  public double computeNormalDistance(double x, double y, double z);
-
-  /**
-   * Compute the square of this shape's normal "distance" to the GeoPoint.
-   * A return value of Double.MAX_VALUE should be returned for
-   * points outside of the shape.
-   *
-   * @param point is the point to compute the distance to.
-   * @return the square of the normal distance, defined as the perpendicular
-   * distance from
-   * from the point to one of the shape's bounding plane.  Normal
-   * distances can therefore typically only go up to PI/2, except
-   * when they represent the sum of a sequence of normal distances.
-   */
-  public double computeSquaredNormalDistance(GeoPoint point);
-
-  /**
-   * Compute the square of this shape's normal "distance" to the GeoPoint.
-   * A return value of Double.MAX_VALUE should be returned for
-   * points outside of the shape.
-   *
-   * @param x is the point's unit x coordinate (using U.S. convention).
-   * @param y is the point's unit y coordinate (using U.S. convention).
-   * @param z is the point's unit z coordinate (using U.S. convention).
-   * @return the square of the  normal distance, defined as the perpendicular
-   * distance from
-   * from the point to one of the shape's bounding plane.  Normal
-   * distances can therefore typically only go up to PI/2, except
-   * when they represent the sum of a sequence of normal distances.
-   */
-  public double computeSquaredNormalDistance(double x, double y, double z);
-
-  /**
-   * Compute this shape's linear "distance" to the GeoPoint.
-   * A return value of Double.MAX_VALUE should be returned for
-   * points outside of the shape.
-   *
-   * @param point is the point to compute the distance to.
-   * @return the linear (or chord) distance, defined as the distance from
-   * from the point to the nearest point on the unit sphere and on one of the shape's
-   * bounding planes.  Linear distances can therefore typically go up to PI,
-   * except when they represent the sum of a sequence of linear distances.
-   */
-  public double computeLinearDistance(GeoPoint point);
-
-  /**
-   * Compute this shape's linear "distance" to the GeoPoint.
-   * A return value of Double.MAX_VALUE should be returned for
-   * points outside of the shape.
-   *
-   * @param x is the point's unit x coordinate (using U.S. convention).
-   * @param y is the point's unit y coordinate (using U.S. convention).
-   * @param z is the point's unit z coordinate (using U.S. convention).
-   * @return the linear (or chord) distance, defined as the distance from
-   * from the point to the nearest point on the unit sphere and on one of the shape's
-   * bounding planes.  Linear distances can therefore typically go up to PI,
-   * except when they represent the sum of a sequence of linear distances.
-   */
-  public double computeLinearDistance(double x, double y, double z);
+  
+  // The following methods compute distances from the shape to a point
+  // expected to be INSIDE the shape.  Typically a value of Double.MAX_VALUE
+  // is returned for points that happen to be outside the shape.
 
   /**
-   * Compute the square of this shape's linear "distance" to the GeoPoint.
+   * Compute this shape's <em>internal</em> "distance" to the GeoPoint.
+   * Implementations should clarify how this is computed when it's non-obvious.
    * A return value of Double.MAX_VALUE should be returned for
    * points outside of the shape.
    *
+   * @param distanceStyle is the distance style.
    * @param point is the point to compute the distance to.
-   * @return the square of the linear (or chord) distance, defined as the
-   * distance from
-   * from the point to the nearest point on the unit sphere and on one of the shape's
-   * bounding planes.  Linear distances can therefore typically go up to PI,
-   * except when they represent the sum of a sequence of linear distances.
+   * @return the distance.
    */
-  public double computeSquaredLinearDistance(GeoPoint point);
+  public double computeDistance(final DistanceStyle distanceStyle, final GeoPoint point);
 
   /**
-   * Compute the square of this shape's linear "distance" to the GeoPoint.
+   * Compute this shape's <em>internal</em> "distance" to the GeoPoint.
+   * Implementations should clarify how this is computed when it's non-obvious.
    * A return value of Double.MAX_VALUE should be returned for
    * points outside of the shape.
    *
    * @param x is the point's unit x coordinate (using U.S. convention).
    * @param y is the point's unit y coordinate (using U.S. convention).
    * @param z is the point's unit z coordinate (using U.S. convention).
-   * @return the square of the linear (or chord) distance, defined as the distance from
-   * from the point to the nearest point on the unit sphere and on one of the shape's
-   * bounding planes.  Linear distances can therefore typically go up to PI,
-   * except when they represent the sum of a sequence of linear distances.
-   */
-  public double computeSquaredLinearDistance(double x, double y, double z);
-
-  /**
-   * Compute a true, accurate, great-circle distance to a point.
-   * Double.MAX_VALUE indicates a point is outside of the shape.
-   *
-   * @param point is the point.
    * @return the distance.
    */
-  public double computeArcDistance(GeoPoint point);
+  public double computeDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
 
 }

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoLatitudeZone.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoLatitudeZone.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoLatitudeZone.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoLatitudeZone.java Wed Jul  1 02:16:55 2015
@@ -71,12 +71,6 @@ public class GeoLatitudeZone extends Geo
   }
 
   @Override
-  public boolean isWithin(final Vector point) {
-    return topPlane.isWithin(point) &&
-        bottomPlane.isWithin(point);
-  }
-
-  @Override
   public boolean isWithin(final double x, final double y, final double z) {
     return topPlane.isWithin(x, y, z) &&
         bottomPlane.isWithin(x, y, z);
@@ -94,11 +88,6 @@ public class GeoLatitudeZone extends Geo
     return maxCosLat * Math.PI;
   }
 
-  /**
-   * Returns the center of a circle into which the area will be inscribed.
-   *
-   * @return the center.
-   */
   @Override
   public GeoPoint getCenter() {
     // This is totally arbitrary and only a cartesian could agree with it.
@@ -116,15 +105,6 @@ public class GeoLatitudeZone extends Geo
         p.intersects(planetModel, bottomPlane, notablePoints, planePoints, bounds, topPlane);
   }
 
-  /**
-   * Compute longitude/latitude bounds for the shape.
-   *
-   * @param bounds is the optional input bounds object.  If this is null,
-   *               a bounds object will be created.  Otherwise, the input object will be modified.
-   * @return a Bounds object describing the shape's bounds.  If the bounds cannot
-   * be computed, then return a Bounds object with noLongitudeBound,
-   * noTopLatitudeBound, and noBottomLatitudeBound.
-   */
   @Override
   public Bounds getBounds(Bounds bounds) {
     if (bounds == null)
@@ -174,6 +154,14 @@ public class GeoLatitudeZone extends Geo
   }
 
   @Override
+  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    final double topDistance = distanceStyle.computeDistance(planetModel, topPlane, x,y,z, bottomPlane);
+    final double bottomDistance = distanceStyle.computeDistance(planetModel, bottomPlane, x,y,z, topPlane);
+
+    return Math.min(topDistance, bottomDistance);
+  }
+
+  @Override
   public boolean equals(Object o) {
     if (!(o instanceof GeoLatitudeZone))
       return false;

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoLongitudeSlice.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoLongitudeSlice.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoLongitudeSlice.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoLongitudeSlice.java Wed Jul  1 02:16:55 2015
@@ -20,7 +20,7 @@ package org.apache.lucene.spatial.spatia
 /**
  * Bounding box limited on left and right.
  * The left-right maximum extent for this shape is PI; for anything larger, use
- * GeoWideLongitudeSlice.
+ * {@link GeoWideLongitudeSlice}.
  *
  * @lucene.internal
  */
@@ -92,12 +92,6 @@ public class GeoLongitudeSlice extends G
   }
 
   @Override
-  public boolean isWithin(final Vector point) {
-    return leftPlane.isWithin(point) &&
-        rightPlane.isWithin(point);
-  }
-
-  @Override
   public boolean isWithin(final double x, final double y, final double z) {
     return leftPlane.isWithin(x, y, z) &&
         rightPlane.isWithin(x, y, z);
@@ -112,11 +106,6 @@ public class GeoLongitudeSlice extends G
     return Math.max(Math.PI * 0.5, extent * 0.5);
   }
 
-  /**
-   * Returns the center of a circle into which the area will be inscribed.
-   *
-   * @return the center.
-   */
   @Override
   public GeoPoint getCenter() {
     return centerPoint;
@@ -133,15 +122,6 @@ public class GeoLongitudeSlice extends G
         p.intersects(planetModel, rightPlane, notablePoints, planePoints, bounds, leftPlane);
   }
 
-  /**
-   * Compute longitude/latitude bounds for the shape.
-   *
-   * @param bounds is the optional input bounds object.  If this is null,
-   *               a bounds object will be created.  Otherwise, the input object will be modified.
-   * @return a Bounds object describing the shape's bounds.  If the bounds cannot
-   * be computed, then return a Bounds object with noLongitudeBound,
-   * noTopLatitudeBound, and noBottomLatitudeBound.
-   */
   @Override
   public Bounds getBounds(Bounds bounds) {
     if (bounds == null)
@@ -179,6 +159,20 @@ public class GeoLongitudeSlice extends G
   }
 
   @Override
+  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    final double leftDistance = distanceStyle.computeDistance(planetModel, leftPlane, x,y,z, rightPlane);
+    final double rightDistance = distanceStyle.computeDistance(planetModel, rightPlane, x,y,z, leftPlane);
+    
+    final double northDistance = distanceStyle.computeDistance(planetModel.NORTH_POLE, x,y,z);
+    final double southDistance = distanceStyle.computeDistance(planetModel.SOUTH_POLE, x,y,z);
+    
+    return
+      Math.min(
+        Math.min(northDistance, southDistance),
+        Math.min(leftDistance, rightDistance));
+  }
+
+  @Override
   public boolean equals(Object o) {
     if (!(o instanceof GeoLongitudeSlice))
       return false;

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoMembershipShape.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoMembershipShape.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoMembershipShape.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoMembershipShape.java Wed Jul  1 02:16:55 2015
@@ -23,6 +23,6 @@ package org.apache.lucene.spatial.spatia
  *
  * @lucene.experimental
  */
-public interface GeoMembershipShape extends GeoShape, Membership {
+public interface GeoMembershipShape extends GeoShape, GeoOutsideDistance, Membership {
 
 }

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoNorthLatitudeZone.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoNorthLatitudeZone.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoNorthLatitudeZone.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoNorthLatitudeZone.java Wed Jul  1 02:16:55 2015
@@ -60,12 +60,6 @@ public class GeoNorthLatitudeZone extend
   }
 
   @Override
-  public boolean isWithin(final Vector point) {
-    return
-        bottomPlane.isWithin(point);
-  }
-
-  @Override
   public boolean isWithin(final double x, final double y, final double z) {
     return
         bottomPlane.isWithin(x, y, z);
@@ -81,11 +75,6 @@ public class GeoNorthLatitudeZone extend
     return maxCosLat * Math.PI;
   }
 
-  /**
-   * Returns the center of a circle into which the area will be inscribed.
-   *
-   * @return the center.
-   */
   @Override
   public GeoPoint getCenter() {
     return interiorPoint;
@@ -102,15 +91,6 @@ public class GeoNorthLatitudeZone extend
         p.intersects(planetModel, bottomPlane, notablePoints, planePoints, bounds);
   }
 
-  /**
-   * Compute longitude/latitude bounds for the shape.
-   *
-   * @param bounds is the optional input bounds object.  If this is null,
-   *               a bounds object will be created.  Otherwise, the input object will be modified.
-   * @return a Bounds object describing the shape's bounds.  If the bounds cannot
-   * be computed, then return a Bounds object with noLongitudeBound,
-   * noTopLatitudeBound, and noBottomLatitudeBound.
-   */
   @Override
   public Bounds getBounds(Bounds bounds) {
     if (bounds == null)
@@ -133,8 +113,7 @@ public class GeoNorthLatitudeZone extend
     // Second, the shortcut of seeing whether endpoints are in/out is not going to
     // work with no area endpoints.  So we rely entirely on intersections.
 
-    if (
-        path.intersects(bottomPlane, planePoints))
+    if (path.intersects(bottomPlane, planePoints))
       return OVERLAPS;
 
     // There is another case for latitude zones only.  This is when the boundaries of the shape all fit
@@ -153,6 +132,11 @@ public class GeoNorthLatitudeZone extend
   }
 
   @Override
+  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    return distanceStyle.computeDistance(planetModel, bottomPlane, x,y,z);
+  }
+
+  @Override
   public boolean equals(Object o) {
     if (!(o instanceof GeoNorthLatitudeZone))
       return false;

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoNorthRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoNorthRectangle.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoNorthRectangle.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoNorthRectangle.java Wed Jul  1 02:16:55 2015
@@ -21,7 +21,7 @@ package org.apache.lucene.spatial.spatia
  * Bounding box limited on three sides (bottom lat, left lon, right lon), including
  * the north pole.
  * The left-right maximum extent for this shape is PI; for anything larger, use
- * GeoWideNorthRectangle.
+ * {@link GeoWideNorthRectangle}.
  *
  * @lucene.internal
  */
@@ -123,14 +123,6 @@ public class GeoNorthRectangle extends G
   }
 
   @Override
-  public boolean isWithin(final Vector point) {
-    return
-        bottomPlane.isWithin(point) &&
-            leftPlane.isWithin(point) &&
-            rightPlane.isWithin(point);
-  }
-
-  @Override
   public boolean isWithin(final double x, final double y, final double z) {
     return
         bottomPlane.isWithin(x, y, z) &&
@@ -171,15 +163,6 @@ public class GeoNorthRectangle extends G
             p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, bottomPlane);
   }
 
-  /**
-   * Compute longitude/latitude bounds for the shape.
-   *
-   * @param bounds is the optional input bounds object.  If this is null,
-   *               a bounds object will be created.  Otherwise, the input object will be modified.
-   * @return a Bounds object describing the shape's bounds.  If the bounds cannot
-   * be computed, then return a Bounds object with noLongitudeBound,
-   * noTopLatitudeBound, and noBottomLatitudeBound.
-   */
   @Override
   public Bounds getBounds(Bounds bounds) {
     if (bounds == null)
@@ -227,6 +210,23 @@ public class GeoNorthRectangle extends G
   }
 
   @Override
+  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    final double bottomDistance = distanceStyle.computeDistance(planetModel, bottomPlane, x,y,z, leftPlane, rightPlane);
+    final double leftDistance = distanceStyle.computeDistance(planetModel, leftPlane, x,y,z, rightPlane, bottomPlane);
+    final double rightDistance = distanceStyle.computeDistance(planetModel, rightPlane, x,y,z, leftPlane, bottomPlane);
+    
+    final double LRHCDistance = distanceStyle.computeDistance(LRHC, x,y,z);
+    final double LLHCDistance = distanceStyle.computeDistance(LLHC, x,y,z);
+    
+    return
+      Math.min(
+        bottomDistance,
+        Math.min(
+          Math.min(leftDistance, rightDistance),
+          Math.min(LRHCDistance, LLHCDistance)));
+  }
+
+  @Override
   public boolean equals(Object o) {
     if (!(o instanceof GeoNorthRectangle))
       return false;

Copied: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoOutsideDistance.java (from r1688545, lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoOutsideDistance.java)
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoOutsideDistance.java?p2=lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoOutsideDistance.java&p1=lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoOutsideDistance.java&r1=1688545&r2=1688546&rev=1688546&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoOutsideDistance.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoOutsideDistance.java Wed Jul  1 02:16:55 2015
@@ -36,9 +36,7 @@ public interface GeoOutsideDistance exte
    * @param point is the point to compute the distance to.
    * @return the distance.
    */
-  public default double computeOutsideDistance(final DistanceStyle distanceStyle, final GeoPoint point) {
-    return computeOutsideDistance(distanceStyle, point.x, point.y, point.z);
-  }
+  public double computeOutsideDistance(final DistanceStyle distanceStyle, final GeoPoint point);
 
   /**
    * Compute this shape's distance to the GeoPoint.

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPath.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPath.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPath.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPath.java Wed Jul  1 02:16:55 2015
@@ -19,17 +19,19 @@ package org.apache.lucene.spatial.spatia
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
- * GeoSearchableShape representing a path across the surface of the globe,
+ * GeoShape representing a path across the surface of the globe,
  * with a specified half-width.  Path is described by a series of points.
  * Distances are measured from the starting point along the path, and then at right
  * angles to the path.
  *
  * @lucene.experimental
  */
-public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
+public class GeoPath extends GeoBaseDistanceShape {
   
   public final double cutoffAngle;
 
@@ -83,7 +85,7 @@ public class GeoPath extends GeoBaseExte
     GeoPoint lastPoint = null;
     for (final GeoPoint end : points) {
       if (lastPoint != null) {
-        final Plane normalizedConnectingPlane = new Plane(lastPoint, end).normalize();
+        final Plane normalizedConnectingPlane = new Plane(lastPoint, end);
         if (normalizedConnectingPlane == null) {
           continue;
         }
@@ -166,173 +168,46 @@ public class GeoPath extends GeoBaseExte
 
   }
 
-  /**
-   * Compute an estimate of "distance" to the GeoPoint.
-   * A return value of Double.MAX_VALUE should be returned for
-   * points outside of the shape.
-   */
-  @Override
-  public double computeNormalDistance(final GeoPoint point) {
-    // Algorithm:
-    // (1) If the point is within any of the segments along the path, return that value.
-    // (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.pathNormalDistance(point);
-      if (distance != Double.MAX_VALUE)
-        return currentDistance + distance;
-      currentDistance += segment.fullNormalDistance;
-    }
-
-    int segmentIndex = 0;
-    currentDistance = 0.0;
-    for (SegmentEndpoint endpoint : endPoints) {
-      double distance = endpoint.pathNormalDistance(point);
-      if (distance != Double.MAX_VALUE)
-        return currentDistance + distance;
-      if (segmentIndex < segments.size())
-        currentDistance += segments.get(segmentIndex++).fullNormalDistance;
-    }
-
-    return Double.MAX_VALUE;
-  }
-
-  /**
-   * Compute an estimate of "distance" to the GeoPoint.
-   * A return value of Double.MAX_VALUE should be returned for
-   * points outside of the shape.
-   */
-  @Override
-  public double computeNormalDistance(final double x, final double y, final double z) {
-    return computeNormalDistance(new GeoPoint(x, y, z));
-  }
-
-  /**
-   * Compute a squared estimate of the "distance" to the
-   * GeoPoint.  Double.MAX_VALUE indicates a point outside of the
-   * shape.
-   */
-  @Override
-  public double computeSquaredNormalDistance(final GeoPoint point) {
-    double pd = computeNormalDistance(point);
-    if (pd == Double.MAX_VALUE)
-      return pd;
-    return pd * pd;
-  }
-
-  /**
-   * Compute a squared estimate of the "distance" to the
-   * GeoPoint.  Double.MAX_VALUE indicates a point outside of the
-   * shape.
-   */
-  @Override
-  public double computeSquaredNormalDistance(final double x, final double y, final double z) {
-    return computeSquaredNormalDistance(new GeoPoint(x, y, z));
-  }
-
-  /**
-   * Compute a linear distance to the point.
-   */
-  @Override
-  public double computeLinearDistance(final GeoPoint point) {
-    // Algorithm:
-    // (1) If the point is within any of the segments along the path, return that value.
-    // (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.pathLinearDistance(point);
-      if (distance != Double.MAX_VALUE)
-        return currentDistance + distance;
-      currentDistance += segment.fullLinearDistance;
-    }
-
-    int segmentIndex = 0;
-    currentDistance = 0.0;
-    for (SegmentEndpoint endpoint : endPoints) {
-      double distance = endpoint.pathLinearDistance(point);
-      if (distance != Double.MAX_VALUE)
-        return currentDistance + distance;
-      if (segmentIndex < segments.size())
-        currentDistance += segments.get(segmentIndex++).fullLinearDistance;
-    }
-
-    return Double.MAX_VALUE;
-  }
-
-  /**
-   * Compute a linear distance to the point.
-   */
-  @Override
-  public double computeLinearDistance(final double x, final double y, final double z) {
-    return computeLinearDistance(new GeoPoint(x, y, z));
-  }
-
-  /**
-   * Compute a squared linear distance to the vector.
-   */
-  @Override
-  public double computeSquaredLinearDistance(final GeoPoint point) {
-    double pd = computeLinearDistance(point);
-    if (pd == Double.MAX_VALUE)
-      return pd;
-    return pd * pd;
-  }
-
-  /**
-   * Compute a squared linear distance to the vector.
-   */
-  @Override
-  public double computeSquaredLinearDistance(final double x, final double y, final double z) {
-    return computeSquaredLinearDistance(new GeoPoint(x, y, z));
-  }
-
-  /**
-   * Compute a true, accurate, great-circle distance.
-   * Double.MAX_VALUE indicates a point is outside of the shape.
-   */
   @Override
-  public double computeArcDistance(final GeoPoint point) {
+  protected double distance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
     // Algorithm:
     // (1) If the point is within any of the segments along the path, return that value.
     // (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(point);
+      double distance = segment.pathDistance(planetModel, distanceStyle, x,y,z);
       if (distance != Double.MAX_VALUE)
         return currentDistance + distance;
-      currentDistance += segment.fullDistance;
+      currentDistance += segment.fullPathDistance(distanceStyle);
     }
 
     int segmentIndex = 0;
     currentDistance = 0.0;
     for (SegmentEndpoint endpoint : endPoints) {
-      double distance = endpoint.pathDistance(point);
+      double distance = endpoint.pathDistance(distanceStyle, x, y, z);
       if (distance != Double.MAX_VALUE)
         return currentDistance + distance;
       if (segmentIndex < segments.size())
-        currentDistance += segments.get(segmentIndex++).fullDistance;
+        currentDistance += segments.get(segmentIndex++).fullPathDistance(distanceStyle);
     }
 
     return Double.MAX_VALUE;
   }
 
   @Override
-  public boolean isWithin(final Vector point) {
-    //System.err.println("Assessing whether point "+point+" is within geopath "+this);
-    for (SegmentEndpoint pathPoint : endPoints) {
-      if (pathPoint.isWithin(point)) {
-        //System.err.println(" point is within SegmentEndpoint "+pathPoint);
-        return true;
-      }
-    }
-    for (PathSegment pathSegment : segments) {
-      if (pathSegment.isWithin(point)) {
-        //System.err.println(" point is within PathSegment "+pathSegment);
-        return true;
-      }
+  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) {
+      final double newDistance = endpoint.outsideDistance(distanceStyle, x,y,z);
+      if (newDistance < minDistance)
+        minDistance = newDistance;
+    }
+    for (final PathSegment segment : segments) {
+      final double newDistance = segment.outsideDistance(planetModel, distanceStyle, x, y, z);
+      if (newDistance < minDistance)
+        minDistance = newDistance;
     }
-    //System.err.println(" point is not within geopath");
-    return false;
+    return minDistance;
   }
 
   @Override
@@ -380,15 +255,6 @@ public class GeoPath extends GeoBaseExte
     return false;
   }
 
-  /**
-   * Compute longitude/latitude bounds for the shape.
-   *
-   * @param bounds is the optional input bounds object.  If this is null,
-   *               a bounds object will be created.  Otherwise, the input object will be modified.
-   * @return a Bounds object describing the shape's bounds.  If the bounds cannot
-   * be computed, then return a Bounds object with noLongitudeBound,
-   * noTopLatitudeBound, and noBottomLatitudeBound.
-   */
   @Override
   public Bounds getBounds(Bounds bounds) {
     bounds = super.getBounds(bounds);
@@ -562,22 +428,14 @@ public class GeoPath extends GeoBaseExte
       return circlePlane.isWithin(x, y, z);
     }
 
-    public double pathDistance(final GeoPoint point) {
-      if (!isWithin(point))
-        return Double.MAX_VALUE;
-      return this.point.arcDistance(point);
-    }
-
-    public double pathNormalDistance(final GeoPoint point) {
-      if (!isWithin(point))
+    public double pathDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+      if (!isWithin(x,y,z))
         return Double.MAX_VALUE;
-      return this.point.normalDistance(point);
+      return distanceStyle.computeDistance(this.point, x, y, z);
     }
 
-    public double pathLinearDistance(final GeoPoint point) {
-      if (!isWithin(point))
-        return Double.MAX_VALUE;
-      return this.point.linearDistance(point);
+    public double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+      return distanceStyle.computeDistance(this.point, x, y, z);
     }
 
     public boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
@@ -614,14 +472,12 @@ public class GeoPath extends GeoBaseExte
   }
 
   /**
-   * This is the precalculated data for a path segment.
+   * This is the pre-calculated data for a path segment.
    */
   public static class PathSegment {
     public final GeoPoint start;
     public final GeoPoint end;
-    public final double fullDistance;
-    public final double fullNormalDistance;
-    public final double fullLinearDistance;
+    public final Map<DistanceStyle,Double> fullDistanceCache = new HashMap<DistanceStyle,Double>();
     public final Plane normalizedConnectingPlane;
     public final SidedPlane upperConnectingPlane;
     public final SidedPlane lowerConnectingPlane;
@@ -644,9 +500,6 @@ public class GeoPath extends GeoBaseExte
       this.normalizedConnectingPlane = normalizedConnectingPlane;
       this.planeBoundingOffset = planeBoundingOffset;
 
-      fullDistance = start.arcDistance(end);
-      fullNormalDistance = start.normalDistance(end);
-      fullLinearDistance = start.linearDistance(end);
       // Either start or end should be on the correct side
       upperConnectingPlane = new SidedPlane(start, normalizedConnectingPlane, -planeBoundingOffset);
       lowerConnectingPlane = new SidedPlane(start, normalizedConnectingPlane, planeBoundingOffset);
@@ -684,6 +537,17 @@ public class GeoPath extends GeoBaseExte
       endCutoffPlanePoints = new GeoPoint[]{URHC, LRHC};
     }
 
+    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));
+          fullDistanceCache.put(distanceStyle, dist);
+        }
+        return dist.doubleValue();
+      }
+    }
+    
     public boolean isWithin(final Vector point) {
       //System.err.println(" assessing whether point "+point+" is within path segment "+this);
       //System.err.println("  within "+startCutoffPlane+": "+startCutoffPlane.isWithin(point));
@@ -704,74 +568,58 @@ public class GeoPath extends GeoBaseExte
           lowerConnectingPlane.isWithin(x, y, z);
     }
 
-    public double pathDistance(final GeoPoint point) {
-      if (!isWithin(point))
-        return Double.MAX_VALUE;
-
-      // Compute the distance, filling in both components.
-      final double perpDistance = Math.PI * 0.5 - Tools.safeAcos(Math.abs(normalizedConnectingPlane.evaluate(point)));
-      final Plane normalizedPerpPlane = new Plane(normalizedConnectingPlane, point).normalize();
-      final double pathDistance = Math.PI * 0.5 - Tools.safeAcos(Math.abs(normalizedPerpPlane.evaluate(start)));
-      return perpDistance + pathDistance;
-    }
-
-    public double pathNormalDistance(final GeoPoint point) {
-      if (!isWithin(point))
-        return Double.MAX_VALUE;
-
-      final double pointEval = Math.abs(normalizedConnectingPlane.evaluate(point));
-
-      // Want no allocations or expensive operations!  so we do this the hard way
-      final double perpX = normalizedConnectingPlane.y * point.z - normalizedConnectingPlane.z * point.y;
-      final double perpY = normalizedConnectingPlane.z * point.x - normalizedConnectingPlane.x * point.z;
-      final double perpZ = normalizedConnectingPlane.x * point.y - normalizedConnectingPlane.y * point.x;
-
-      // If we have a degenerate line, then just compute the normal distance from point x to the start
-      if (Math.abs(perpX) < Vector.MINIMUM_RESOLUTION && Math.abs(perpY) < Vector.MINIMUM_RESOLUTION && Math.abs(perpZ) < Vector.MINIMUM_RESOLUTION)
-        return point.normalDistance(start);
-
-      final double normFactor = 1.0 / Math.sqrt(perpX * perpX + perpY * perpY + perpZ * perpZ);
-      final double perpEval = Math.abs(perpX * start.x + perpY * start.y + perpZ * start.z);
-      return perpEval * normFactor + pointEval;
-    }
-
-    public double pathLinearDistance(final GeoPoint point) {
-      if (!isWithin(point))
+    public double pathDistance(final PlanetModel planetModel, final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+      if (!isWithin(x,y,z))
         return Double.MAX_VALUE;
 
-      // We have a normalized connecting plane.
-      // First, compute the perpendicular plane.
+      // (1) Compute normalizedPerpPlane.  If degenerate, then return point distance from start to point.
       // Want no allocations or expensive operations!  so we do this the hard way
-      final double perpX = normalizedConnectingPlane.y * point.z - normalizedConnectingPlane.z * point.y;
-      final double perpY = normalizedConnectingPlane.z * point.x - normalizedConnectingPlane.x * point.z;
-      final double perpZ = normalizedConnectingPlane.x * point.y - normalizedConnectingPlane.y * point.x;
-
-      // If we have a degenerate line, then just compute the normal distance from point x to the start
-      if (Math.abs(perpX) < Vector.MINIMUM_RESOLUTION && Math.abs(perpY) < Vector.MINIMUM_RESOLUTION && Math.abs(perpZ) < Vector.MINIMUM_RESOLUTION)
-        return point.linearDistance(start);
-
-      // Next, we need the vector of the line, which is the cross product of the normalized connecting plane
-      // and the perpendicular plane that we just calculated.
-      final double lineX = normalizedConnectingPlane.y * perpZ - normalizedConnectingPlane.z * perpY;
-      final double lineY = normalizedConnectingPlane.z * perpX - normalizedConnectingPlane.x * perpZ;
-      final double lineZ = normalizedConnectingPlane.x * perpY - normalizedConnectingPlane.y * perpX;
-
-      // Now, compute a normalization factor
-      final double normalizer = 1.0 / Math.sqrt(lineX * lineX + lineY * lineY + lineZ * lineZ);
-
-      // Pick which point by using bounding planes
-      double normLineX = lineX * normalizer;
-      double normLineY = lineY * normalizer;
-      double normLineZ = lineZ * normalizer;
-      if (!startCutoffPlane.isWithin(normLineX, normLineY, normLineZ) ||
-          !endCutoffPlane.isWithin(normLineX, normLineY, normLineZ)) {
-        normLineX = -normLineX;
-        normLineY = -normLineY;
-        normLineZ = -normLineZ;
-      }
-
-      // Compute linear distance for the two points
-      return point.linearDistance(normLineX, normLineY, normLineZ) + start.linearDistance(normLineX, normLineY, normLineZ);
+      final double perpX = normalizedConnectingPlane.y * z - normalizedConnectingPlane.z * y;
+      final double perpY = normalizedConnectingPlane.z * x - normalizedConnectingPlane.x * z;
+      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);
+      final double normFactor = 1.0/magnitude;
+      final Plane normalizedPerpPlane = new Plane(perpX * normFactor, perpY * normFactor, perpZ * normFactor, 0.0);
+      
+      // Old computation: too expensive, because it calculates the intersection point twice.
+      //return distanceStyle.computeDistance(planetModel, normalizedConnectingPlane, x, y, z, startCutoffPlane, endCutoffPlane) +
+      //  distanceStyle.computeDistance(planetModel, normalizedPerpPlane, start.x, start.y, start.z, upperConnectingPlane, lowerConnectingPlane);
+
+      final GeoPoint[] intersectionPoints = normalizedConnectingPlane.findIntersections(planetModel, normalizedPerpPlane);
+      GeoPoint thePoint;
+      if (intersectionPoints.length == 0)
+        throw new RuntimeException("Can't find world intersection for point x="+x+" y="+y+" z="+z);
+      else if (intersectionPoints.length == 1)
+        thePoint = intersectionPoints[0];
+      else {
+        if (startCutoffPlane.isWithin(intersectionPoints[0]) && endCutoffPlane.isWithin(intersectionPoints[0]))
+          thePoint = intersectionPoints[0];
+        else if (startCutoffPlane.isWithin(intersectionPoints[1]) && endCutoffPlane.isWithin(intersectionPoints[1]))
+          thePoint = intersectionPoints[1];
+        else
+          throw new RuntimeException("Can't find world intersection for point x="+x+" y="+y+" z="+z);
+      }
+      return distanceStyle.computeDistance(thePoint, x, y, z) + distanceStyle.computeDistance(start, thePoint.x, thePoint.y, thePoint.z);
+    }
+
+    public double outsideDistance(final PlanetModel planetModel, final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+      final double upperDistance = distanceStyle.computeDistance(planetModel, upperConnectingPlane, x,y,z, lowerConnectingPlane, startCutoffPlane, endCutoffPlane);
+      final double lowerDistance = distanceStyle.computeDistance(planetModel, lowerConnectingPlane, x,y,z, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
+      final double startDistance = distanceStyle.computeDistance(planetModel, startCutoffPlane, x,y,z, endCutoffPlane, lowerConnectingPlane, upperConnectingPlane);
+      final double endDistance = distanceStyle.computeDistance(planetModel, endCutoffPlane, x,y,z, startCutoffPlane, lowerConnectingPlane, upperConnectingPlane);
+      final double ULHCDistance = distanceStyle.computeDistance(ULHC, x,y,z);
+      final double URHCDistance = distanceStyle.computeDistance(URHC, x,y,z);
+      final double LLHCDistance = distanceStyle.computeDistance(LLHC, x,y,z);
+      final double LRHCDistance = distanceStyle.computeDistance(LRHC, x,y,z);
+      return Math.min(
+        Math.min(
+          Math.min(upperDistance,lowerDistance),
+          Math.min(startDistance,endDistance)),
+        Math.min(
+          Math.min(ULHCDistance, URHCDistance),
+          Math.min(LLHCDistance, LRHCDistance)));
     }
 
     public boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
@@ -790,12 +638,6 @@ public class GeoPath extends GeoBaseExte
       lowerConnectingPlane.recordBounds(planetModel, bounds, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
       startCutoffPlane.recordBounds(planetModel, bounds, endCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
       endCutoffPlane.recordBounds(planetModel, bounds, startCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
-      if (fullDistance >= Math.PI) {
-        // Too large a segment basically means that we can confuse the Bounds object.  Specifically, if our span exceeds 180 degrees
-        // in longitude (which even a segment whose actual length is less than that might if it goes close to a pole).
-        // Unfortunately, we can get arbitrarily close to the pole, so this may still not work in all cases.
-        bounds.noLongitudeBound();
-      }
     }
 
   }

Modified: lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPoint.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPoint.java?rev=1688546&r1=1688545&r2=1688546&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPoint.java (original)
+++ lucene/dev/branches/branch_5x/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPoint.java Wed Jul  1 02:16:55 2015
@@ -18,7 +18,7 @@ package org.apache.lucene.spatial.spatia
  */
 
 /**
- * This class represents a point on the surface of a unit sphere.
+ * This class represents a point on the surface of a sphere or ellipsoid.
  *
  * @lucene.experimental
  */
@@ -124,6 +124,16 @@ public class GeoPoint extends Vector {
     return Tools.safeAcos(dotProduct(v)/(magnitude() * v.magnitude()));
   }
 
+  /** Compute an arc distance between two points.
+   * @param x is the x part of the second point.
+   * @param y is the y part of the second point.
+   * @param z is the z part of the second point.
+   * @return the angle, in radians, between the two points.
+   */
+  public double arcDistance(final double x, final double y, final double z) {
+    return Tools.safeAcos(dotProduct(x,y,z)/(magnitude() * Vector.magnitude(x,y,z)));
+  }
+
   /** Compute the latitude for the point.
    * @return the latitude.
    */