You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mi...@apache.org on 2015/08/17 15:45:43 UTC

svn commit: r1696275 [1/2] - in /lucene/dev/branches/lucene6699/lucene: spatial/src/java/org/apache/lucene/spatial/spatial4j/ spatial/src/test/org/apache/lucene/spatial/spatial4j/ spatial3d/src/java/org/apache/lucene/geo3d/ spatial3d/src/test/org/apach...

Author: mikemccand
Date: Mon Aug 17 13:45:42 2015
New Revision: 1696275

URL: http://svn.apache.org/r1696275
Log:
LUCENE-6699: first cut to support x,y,z bounds

Added:
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LatLonBounds.java   (with props)
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZBounds.java   (with props)
Modified:
    lucene/dev/branches/lucene6699/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/Geo3dShape.java
    lucene/dev/branches/lucene6699/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeRectRelationTestCase.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Bounds.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseShape.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCircle.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCompositeMembershipShape.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoConvexPolygon.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateHorizontalLine.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLatitudeZone.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLongitudeSlice.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegeneratePoint.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateVerticalLine.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLatitudeZone.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLongitudeSlice.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthLatitudeZone.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthRectangle.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPath.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoRectangle.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoShape.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthLatitudeZone.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthRectangle.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideDegenerateHorizontalLine.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideLongitudeSlice.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideNorthRectangle.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideRectangle.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideSouthRectangle.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWorld.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Plane.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoBBoxTest.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoCircleTest.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoConvexPolygonTest.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoModelTest.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoPathTest.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoPolygonTest.java

Modified: lucene/dev/branches/lucene6699/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/Geo3dShape.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/Geo3dShape.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/Geo3dShape.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/Geo3dShape.java Mon Aug 17 13:45:42 2015
@@ -24,7 +24,7 @@ import com.spatial4j.core.shape.Rectangl
 import com.spatial4j.core.shape.Shape;
 import com.spatial4j.core.shape.SpatialRelation;
 import com.spatial4j.core.shape.impl.RectangleImpl;
-import org.apache.lucene.geo3d.Bounds;
+import org.apache.lucene.geo3d.LatLonBounds;
 import org.apache.lucene.geo3d.GeoArea;
 import org.apache.lucene.geo3d.GeoAreaFactory;
 import org.apache.lucene.geo3d.GeoPoint;
@@ -107,7 +107,8 @@ public class Geo3dShape implements Shape
   public Rectangle getBoundingBox() {
     Rectangle bbox = this.boundingBox;//volatile read once
     if (bbox == null) {
-      Bounds bounds = shape.getBounds(null);
+      LatLonBounds bounds = new LatLonBounds();
+      shape.getBounds(bounds);
       double leftLon;
       double rightLon;
       if (bounds.checkNoLongitudeBound()) {

Modified: lucene/dev/branches/lucene6699/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeRectRelationTestCase.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeRectRelationTestCase.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeRectRelationTestCase.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeRectRelationTestCase.java Mon Aug 17 13:45:42 2015
@@ -26,7 +26,7 @@ import com.spatial4j.core.context.Spatia
 import com.spatial4j.core.distance.DistanceUtils;
 import com.spatial4j.core.shape.Circle;
 import com.spatial4j.core.shape.Point;
-import org.apache.lucene.geo3d.Bounds;
+import org.apache.lucene.geo3d.LatLonBounds;
 import org.apache.lucene.geo3d.GeoBBox;
 import org.apache.lucene.geo3d.GeoBBoxFactory;
 import org.apache.lucene.geo3d.GeoCircle;
@@ -58,7 +58,8 @@ public abstract class Geo3dShapeRectRela
   }
 
   protected GeoBBox getBoundingBox(final GeoShape path) {
-    Bounds bounds = path.getBounds(null);
+    LatLonBounds bounds = new LatLonBounds();
+    path.getBounds(bounds);
 
     double leftLon;
     double rightLon;

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Bounds.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Bounds.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Bounds.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Bounds.java Mon Aug 17 13:45:42 2015
@@ -18,7 +18,7 @@ package org.apache.lucene.geo3d;
  */
 
 /**
- * An object for accumulating bounds information.
+ * An interface for accumulating bounds information.
  * The bounds object is initially empty.  Bounding points
  * are then applied by supplying (x,y,z) tuples.  It is also
  * possible to indicate the following edge cases:
@@ -30,356 +30,89 @@ package org.apache.lucene.geo3d;
  *
  * @lucene.experimental
  */
-public class Bounds {
+public interface Bounds {
 
-  /** Set to true if no longitude bounds can be stated */
-  protected boolean noLongitudeBound = false;
-  /** Set to true if no top latitude bound can be stated */
-  protected boolean noTopLatitudeBound = false;
-  /** Set to true if no bottom latitude bound can be stated */
-  protected boolean noBottomLatitudeBound = false;
-
-  /** If non-null, the minimum latitude bound */
-  protected Double minLatitude = null;
-  /** If non-null, the maximum latitude bound */
-  protected Double maxLatitude = null;
-
-  // For longitude bounds, this class needs to worry about keeping track of the distinction
-  // between left-side bounds and right-side bounds.  Points are always submitted in pairs
-  // which have a maximum longitude separation of Math.PI.  It's therefore always possible
-  // to determine which point represents a left bound, and which point represents a right
-  // bound.
-  //
-  // The next problem is how to compare two of the same kind of bound, e.g. two left bounds.
-  // We need to keep track of the leftmost longitude of the shape, but since this is a circle,
-  // this is arbitrary.  What we could try to do instead would be to find a pair of (left,right) bounds such
-  // that:
-  // (1) all other bounds are within, and
-  // (2) the left minus right distance is minimized
-  // Unfortunately, there are still shapes that cannot be summarized in this way correctly.
-  // For example. consider a spiral that entirely circles the globe; we might arbitrarily choose
-  // lat/lon bounds that do not in fact circle the globe.
-  //
-  // One way to handle the longitude issue correctly is therefore to stipulate that we
-  // walk the bounds of the shape in some kind of connected order.  Each point or circle is therefore
-  // added in a sequence.  We also need an interior point to make sure we have the right
-  // choice of longitude bounds.  But even with this, we still can't always choose whether the actual shape
-  // goes right or left.
-  //
-  // We can make the specification truly general by submitting the following in order:
-  // addSide(PlaneSide side, Membership... constraints)
-  // ...
-  // This is unambiguous, but I still can't see yet how this would help compute the bounds.  The plane
-  // solution would in general seem to boil down to the same logic that relies on points along the path
-  // to define the shape boundaries.  I guess the one thing that you do know for a bounded edge is that
-  // the endpoints are actually connected.  But it is not clear whether relationship helps in any way.
-  //
-  // In any case, if we specify shapes by a sequence of planes, we should stipulate that multiple sequences
-  // are allowed, provided they progressively tile an area of the sphere that is connected and sequential.
-  // For example, paths do alternating rectangles and circles, in sequence.  Each sequence member is
-  // described by a sequence of planes.  I think it would also be reasonable to insist that the first segment
-  // of a shape overlap or adjoin the previous shape.
-  //
-  // Here's a way to think about it that might help: Traversing every edge should grow the longitude bounds
-  // in the direction of the traversal.  So if the traversal is always known to be less than PI in total longitude
-  // angle, then it is possible to use the endpoints to determine the unambiguous extension of the envelope.
-  // For example, say you are currently at longitude -0.5.  The next point is at longitude PI-0.1.  You could say
-  // that the difference in longitude going one way around would be beter than the distance the other way
-  // around, and therefore the longitude envelope should be extended accordingly.  But in practice, when an
-  // edge goes near a pole and may be inclined as well, the longer longitude change might be the right path, even
-  // if the arc length is short.  So this too doesn't work.
-  //
-  // Given we have a hard time making an exact match, here's the current proposal.  The proposal is a
-  // heuristic, based on the idea that most areas are small compared to the circumference of the globe.
-  // We keep track of the last point we saw, and take each point as it arrives, and compute its longitude.
-  // Then, we have a choice as to which way to expand the envelope: we can expand by going to the left or
-  // to the right.  We choose the direction with the least longitude difference.  (If we aren't sure,
-  // and can recognize that, we can set "unconstrained in longitude".)
-
-  /** If non-null, the left longitude bound */
-  protected Double leftLongitude = null;
-  /** If non-null, the right longitude bound */
-  protected Double rightLongitude = null;
-
-  /** Construct an empty bounds object */
-  public Bounds() {
-  }
-
-  /** Get maximum latitude, if any.
-   *@return maximum latitude or null.
-   */
-  public Double getMaxLatitude() {
-    return maxLatitude;
-  }
-
-  /** Get minimum latitude, if any.
-   *@return minimum latitude or null.
-   */
-  public Double getMinLatitude() {
-    return minLatitude;
-  }
-
-  /** Get left longitude, if any.
-   *@return left longitude, or null.
-   */
-  public Double getLeftLongitude() {
-    return leftLongitude;
-  }
-
-  /** Get right longitude, if any.
-   *@return right longitude, or null.
-   */
-  public Double getRightLongitude() {
-    return rightLongitude;
-  }
-
-  /** Check if there's no longitude bound.
-   *@return true if no longitude bound.
-   */
-  public boolean checkNoLongitudeBound() {
-    return noLongitudeBound;
-  }
-
-  /** Check if there's no top latitude bound.
-   *@return true if no top latitude bound.
-   */
-  public boolean checkNoTopLatitudeBound() {
-    return noTopLatitudeBound;
-  }
-
-  /** Check if there's no bottom latitude bound.
-   *@return true if no bottom latitude bound.
-   */
-  public boolean checkNoBottomLatitudeBound() {
-    return noBottomLatitudeBound;
-  }
-
-  /** Add a constraint representing a horizontal circle with a
-   * specified z value.
-   *@param z is the z value.
-   *@return the updated Bounds object.
-   */
-  public Bounds addHorizontalCircle(double z) {
-    if (!noTopLatitudeBound || !noBottomLatitudeBound) {
-      // Compute a latitude value
-      double latitude = Math.asin(z);
-      addLatitudeBound(latitude);
-    }
-    return this;
-  }
-
-  /** Add a constraint representing a horizontal circle at
-   * a specific latitude.
+  /** Add a general plane to the bounds description.
+   *@param planetModel is the planet model.
+   *@param plane is the plane.
+   *@param bounds are the membership bounds for points along the arc.
+   */
+  public Bounds addPlane(final PlanetModel planetModel, final Plane plane, final Membership... bounds);
+  
+  /** Add a horizontal plane to the bounds description.
+   * This method should EITHER use the supplied latitude, OR use the supplied
+   * plane, depending on what is most efficient.
+   *@param planetModel is the planet model.
    *@param latitude is the latitude.
-   *@return the updated Bounds object.
-   */
-  public Bounds addLatitudeZone(double latitude) {
-    if (!noTopLatitudeBound || !noBottomLatitudeBound) {
-      addLatitudeBound(latitude);
-    }
-    return this;
-  }
+   *@param horizontalPlane is the plane.
+   *@param bounds are the constraints on the plane.
+   *@return updated Bounds object.
+   */
+  public Bounds addHorizontalPlane(final PlanetModel planetModel,
+    final double latitude,
+    final Plane horizontalPlane,
+    final Membership... bounds);
+    
+  /** Add a vertical plane to the bounds description.
+   * This method should EITHER use the supplied longitude, OR use the supplied
+   * plane, depending on what is most efficient.
+   *@param planetModel is the planet model.
+   *@param longitude is the longitude.
+   *@param verticalPlane is the plane.
+   *@param bounds are the constraints on the plane.
+   *@return updated Bounds object.
+   */
+  public Bounds addVerticalPlane(final PlanetModel planetModel,
+    final double longitude,
+    final Plane verticalPlane,
+    final Membership... bounds);
 
-  /** Add a constraint representing a longitude slice.
-   *@param newLeftLongitude is the left longitude value.
-   *@param newRightLongitude is the right longitude value.
+  /** Add a single point.
+   *@param point is the point.
    *@return the updated Bounds object.
    */
-  public Bounds addLongitudeSlice(double newLeftLongitude, double newRightLongitude) {
-    if (!noLongitudeBound) {
-      addLongitudeBound(newLeftLongitude, newRightLongitude);
-    }
-    return this;
-  }
-
-  /** Update latitude bound.
-   *@param latitude is the latitude.
-   */
-  protected void addLatitudeBound(double latitude) {
-    if (!noTopLatitudeBound && (maxLatitude == null || latitude > maxLatitude))
-      maxLatitude = latitude;
-    if (!noBottomLatitudeBound && (minLatitude == null || latitude < minLatitude))
-      minLatitude = latitude;
-  }
+  public Bounds addPoint(final GeoPoint point);
 
-  /** Update longitude bound.
-   *@param newLeftLongitude is the left longitude.
-   *@param newRightLongitude is the right longitude.
-   */
-  protected void addLongitudeBound(double newLeftLongitude, double newRightLongitude) {
-    if (leftLongitude == null && rightLongitude == null) {
-      leftLongitude = newLeftLongitude;
-      rightLongitude = newRightLongitude;
-    } else {
-      // Map the current range to something monotonically increasing
-      double currentLeftLongitude = leftLongitude;
-      double currentRightLongitude = rightLongitude;
-      if (currentRightLongitude < currentLeftLongitude)
-        currentRightLongitude += 2.0 * Math.PI;
-      double adjustedLeftLongitude = newLeftLongitude;
-      double adjustedRightLongitude = newRightLongitude;
-      if (adjustedRightLongitude < adjustedLeftLongitude)
-        adjustedRightLongitude += 2.0 * Math.PI;
-      // Compare to see what the relationship is
-      if (currentLeftLongitude <= adjustedLeftLongitude && currentRightLongitude >= adjustedRightLongitude) {
-        // No adjustment needed.
-      } else if (currentLeftLongitude >= adjustedLeftLongitude && currentRightLongitude <= adjustedRightLongitude) {
-        // New longitude entirely contains old one
-        leftLongitude = newLeftLongitude;
-        rightLongitude = newRightLongitude;
-      } else {
-        if (currentLeftLongitude > adjustedLeftLongitude) {
-          // New left longitude needed
-          leftLongitude = newLeftLongitude;
-        }
-        if (currentRightLongitude < adjustedRightLongitude) {
-          // New right longitude needed
-          rightLongitude = newRightLongitude;
-        }
-      }
-    }
-    double testRightLongitude = rightLongitude;
-    if (testRightLongitude < leftLongitude)
-      testRightLongitude += Math.PI * 2.0;
-    // If the bound exceeds 180 degrees, we know we could have screwed up.
-    if (testRightLongitude - leftLongitude >= Math.PI) {
-      noLongitudeBound = true;
-      leftLongitude = null;
-      rightLongitude = null;
-    }
-  }
-
-  /** Update longitude bound.
-   *@param longitude is the new longitude value.
+  /** Add an X value.
+   *@param point is the point to take the x value from.
+   *@return the updated object.
    */
-  protected void addLongitudeBound(double longitude) {
-    // If this point is within the current bounds, we're done; otherwise
-    // expand one side or the other.
-    if (leftLongitude == null && rightLongitude == null) {
-      leftLongitude = longitude;
-      rightLongitude = longitude;
-    } else {
-      // Compute whether we're to the right of the left value.  But the left value may be greater than
-      // the right value.
-      double currentLeftLongitude = leftLongitude;
-      double currentRightLongitude = rightLongitude;
-      if (currentRightLongitude < currentLeftLongitude)
-        currentRightLongitude += 2.0 * Math.PI;
-      // We have a range to look at that's going in the right way.
-      // Now, do the same trick with the computed longitude.
-      if (longitude < currentLeftLongitude)
-        longitude += 2.0 * Math.PI;
-
-      if (longitude < currentLeftLongitude || longitude > currentRightLongitude) {
-        // Outside of current bounds.  Consider carefully how we'll expand.
-        double leftExtensionAmt;
-        double rightExtensionAmt;
-        if (longitude < currentLeftLongitude) {
-          leftExtensionAmt = currentLeftLongitude - longitude;
-        } else {
-          leftExtensionAmt = currentLeftLongitude + 2.0 * Math.PI - longitude;
-        }
-        if (longitude > currentRightLongitude) {
-          rightExtensionAmt = longitude - currentRightLongitude;
-        } else {
-          rightExtensionAmt = longitude + 2.0 * Math.PI - currentRightLongitude;
-        }
-        if (leftExtensionAmt < rightExtensionAmt) {
-          currentLeftLongitude = leftLongitude - leftExtensionAmt;
-          while (currentLeftLongitude <= -Math.PI) {
-            currentLeftLongitude += 2.0 * Math.PI;
-          }
-          leftLongitude = currentLeftLongitude;
-        } else {
-          currentRightLongitude = rightLongitude + rightExtensionAmt;
-          while (currentRightLongitude > Math.PI) {
-            currentRightLongitude -= 2.0 * Math.PI;
-          }
-          rightLongitude = currentRightLongitude;
-        }
-      }
-    }
-    double testRightLongitude = rightLongitude;
-    if (testRightLongitude < leftLongitude)
-      testRightLongitude += Math.PI * 2.0;
-    if (testRightLongitude - leftLongitude >= Math.PI) {
-      noLongitudeBound = true;
-      leftLongitude = null;
-      rightLongitude = null;
-    }
-  }
+  public Bounds addXValue(final GeoPoint point);
 
-  /** Add a single point.
-   *@param v is the point vector.
-   *@return the updated Bounds object.
+  /** Add a Y value.
+   *@param point is the point to take the y value from.
+   *@return the updated object.
    */
-  public Bounds addPoint(final Vector v) {
-    return addPoint(v.x, v.y, v.z);
-  }
+  public Bounds addYValue(final GeoPoint point);
 
-  /** Add a single point.
-   *@param x is the point x.
-   *@param y is the point y.
-   *@param z is the point z.
-   *@return the updated Bounds object.
+  /** Add a Z value.
+   *@param point is the point to take the z value from.
+   *@return the updated object.
    */
-  public Bounds addPoint(final double x, final double y, final double z) {
-    if (!noLongitudeBound) {
-      // Get a longitude value
-      double longitude = Math.atan2(y, x);
-      //System.err.println(" add longitude bound at "+longitude * 180.0/Math.PI);
-      addLongitudeBound(longitude);
-    }
-    if (!noTopLatitudeBound || !noBottomLatitudeBound) {
-      // Compute a latitude value
-      double latitude = Math.asin(z/Math.sqrt(z * z + x * x + y * y));
-      addLatitudeBound(latitude);
-    }
-    return this;
-  }
-
-  /** Add a single point.
-   *@param latitude is the point's latitude.
-   *@param longitude is the point's longitude.
+  public Bounds addZValue(final GeoPoint point);
+  
+  /** Signal that the shape exceeds Math.PI in longitude.
+   *@param planetModel is the planet model.
    *@return the updated Bounds object.
    */
-  public Bounds addPoint(double latitude, double longitude) {
-    if (!noLongitudeBound) {
-      // Get a longitude value
-      addLongitudeBound(longitude);
-    }
-    if (!noTopLatitudeBound || !noBottomLatitudeBound) {
-      // Compute a latitude value
-      addLatitudeBound(latitude);
-    }
-    return this;
-  }
-
+  public Bounds isWide(final PlanetModel planetModel);
+  
   /** Signal that there is no longitude bound.
+   *@param planetModel is the planet model.
    *@return the updated Bounds object.
    */
-  public Bounds noLongitudeBound() {
-    noLongitudeBound = true;
-    leftLongitude = null;
-    rightLongitude = null;
-    return this;
-  }
+  public Bounds noLongitudeBound(final PlanetModel planetModel);
 
   /** Signal that there is no top latitude bound.
+   *@param planetModel is the planet model.
    *@return the updated Bounds object.
    */
-  public Bounds noTopLatitudeBound() {
-    noTopLatitudeBound = true;
-    maxLatitude = null;
-    return this;
-  }
+  public Bounds noTopLatitudeBound(final PlanetModel planetModel);
 
   /** Signal that there is no bottom latitude bound.
+   *@param planetModel is the planet model.
    *@return the updated Bounds object.
    */
-  public Bounds noBottomLatitudeBound() {
-    noBottomLatitudeBound = true;
-    minLatitude = null;
-    return this;
-  }
+  public Bounds noBottomLatitudeBound(final PlanetModel planetModel);
+  
 }

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseShape.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseShape.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseShape.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseShape.java Mon Aug 17 13:45:42 2015
@@ -32,16 +32,13 @@ public abstract class GeoBaseShape exten
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
+  public void getBounds(Bounds bounds) {
     if (isWithin(planetModel.NORTH_POLE)) {
-      bounds.noTopLatitudeBound().noLongitudeBound();
+      bounds.noTopLatitudeBound(planetModel).noLongitudeBound(planetModel);
     }
     if (isWithin(planetModel.SOUTH_POLE)) {
-      bounds.noBottomLatitudeBound().noLongitudeBound();
+      bounds.noBottomLatitudeBound(planetModel).noLongitudeBound(planetModel);
     }
-    return bounds;
   }
 
 }

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCircle.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCircle.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCircle.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCircle.java Mon Aug 17 13:45:42 2015
@@ -78,7 +78,7 @@ public class GeoCircle extends GeoBaseDi
       this.edgePoints = new GeoPoint[0];
     } else {
       // Construct normal plane
-      final Plane normalPlane = Plane.constructNormalizedVerticalPlane(upperPoint, lowerPoint, center);
+      final Plane normalPlane = Plane.constructNormalizedZPlane(upperPoint, lowerPoint, center);
       // Construct a sided plane that goes through the two points and whose normal is in the normalPlane.
       this.circlePlane = SidedPlane.constructNormalizedPerpendicularSidedPlane(center, normalPlane, upperPoint, lowerPoint);
       if (circlePlane == null)
@@ -130,16 +130,15 @@ public class GeoCircle extends GeoBaseDi
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    bounds = super.getBounds(bounds);
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
     if (circlePlane == null) {
       // Entire world
-      bounds.noTopLatitudeBound().noBottomLatitudeBound().noLongitudeBound();
-      return bounds;
+      bounds.noTopLatitudeBound(planetModel).noBottomLatitudeBound(planetModel).noLongitudeBound(planetModel);
+      return;
     }
     bounds.addPoint(center);
-    circlePlane.recordBounds(planetModel, bounds);
-    return bounds;
+    bounds.addPlane(planetModel, circlePlane);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCompositeMembershipShape.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCompositeMembershipShape.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCompositeMembershipShape.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCompositeMembershipShape.java Mon Aug 17 13:45:42 2015
@@ -71,13 +71,10 @@ public class GeoCompositeMembershipShape
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
+  public void getBounds(Bounds bounds) {
     for (GeoMembershipShape shape : shapes) {
-      bounds = shape.getBounds(bounds);
+      shape.getBounds(bounds);
     }
-    return bounds;
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoConvexPolygon.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoConvexPolygon.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoConvexPolygon.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoConvexPolygon.java Mon Aug 17 13:45:42 2015
@@ -213,8 +213,8 @@ public class GeoConvexPolygon extends Ge
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    bounds = super.getBounds(bounds);
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
 
     // Add all the points
     for (final GeoPoint point : points) {
@@ -232,14 +232,13 @@ public class GeoConvexPolygon extends Ge
           membershipBounds[count++] = edges[otherIndex];
         }
       }
-      edge.recordBounds(planetModel, bounds, membershipBounds);
+      bounds.addPlane(planetModel, edge, membershipBounds);
     }
 
     if (fullDistance >= Math.PI) {
       // We can't reliably assume that bounds did its longitude calculation right, so we force it to be unbounded.
-      bounds.noLongitudeBound();
+      bounds.noLongitudeBound(planetModel);
     }
-    return bounds;
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateHorizontalLine.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateHorizontalLine.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateHorizontalLine.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateHorizontalLine.java Mon Aug 17 13:45:42 2015
@@ -87,8 +87,8 @@ public class GeoDegenerateHorizontalLine
     final double cosRightLon = Math.cos(rightLon);
 
     // Now build the two points
-    this.LHC = new GeoPoint(planetModel, sinLatitude, sinLeftLon, cosLatitude, cosLeftLon);
-    this.RHC = new GeoPoint(planetModel, sinLatitude, sinRightLon, cosLatitude, cosRightLon);
+    this.LHC = new GeoPoint(planetModel, sinLatitude, sinLeftLon, cosLatitude, cosLeftLon, latitude, leftLon);
+    this.RHC = new GeoPoint(planetModel, sinLatitude, sinRightLon, cosLatitude, cosRightLon, latitude, rightLon);
 
     this.plane = new Plane(planetModel, sinLatitude);
 
@@ -156,11 +156,9 @@ public class GeoDegenerateHorizontalLine
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.addLatitudeZone(latitude).addLongitudeSlice(leftLon, rightLon);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.addHorizontalPlane(planetModel, latitude, plane, leftPlane, rightPlane)
+      .addPoint(LHC).addPoint(RHC);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLatitudeZone.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLatitudeZone.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLatitudeZone.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLatitudeZone.java Mon Aug 17 13:45:42 2015
@@ -86,21 +86,10 @@ public class GeoDegenerateLatitudeZone e
     return p.intersects(planetModel, plane, 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)
-      bounds = new Bounds();
-    bounds.noLongitudeBound().addLatitudeZone(latitude);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.noLongitudeBound(planetModel)
+      .addHorizontalPlane(planetModel, latitude, plane);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLongitudeSlice.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLongitudeSlice.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLongitudeSlice.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLongitudeSlice.java Mon Aug 17 13:45:42 2015
@@ -98,12 +98,10 @@ public class GeoDegenerateLongitudeSlice
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.noTopLatitudeBound().noBottomLatitudeBound();
-    bounds.addLongitudeSlice(longitude, longitude);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.noTopLatitudeBound(planetModel).noBottomLatitudeBound(planetModel)
+      .addVerticalPlane(planetModel, longitude, plane, boundingPlane)
+      .addPoint(planetModel.NORTH_POLE).addPoint(planetModel.SOUTH_POLE);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegeneratePoint.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegeneratePoint.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegeneratePoint.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegeneratePoint.java Mon Aug 17 13:45:42 2015
@@ -74,11 +74,8 @@ public class GeoDegeneratePoint extends
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.addPoint(latitude, longitude);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.addPoint(this);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateVerticalLine.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateVerticalLine.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateVerticalLine.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateVerticalLine.java Mon Aug 17 13:45:42 2015
@@ -77,8 +77,8 @@ public class GeoDegenerateVerticalLine e
     final double cosLongitude = Math.cos(longitude);
 
     // Now build the two points
-    this.UHC = new GeoPoint(planetModel, sinTopLat, sinLongitude, cosTopLat, cosLongitude);
-    this.LHC = new GeoPoint(planetModel, sinBottomLat, sinLongitude, cosBottomLat, cosLongitude);
+    this.UHC = new GeoPoint(planetModel, sinTopLat, sinLongitude, cosTopLat, cosLongitude, topLat, longitude);
+    this.LHC = new GeoPoint(planetModel, sinBottomLat, sinLongitude, cosBottomLat, cosLongitude, bottomLat, longitude);
 
     this.plane = new Plane(cosLongitude, sinLongitude);
 
@@ -146,12 +146,9 @@ public class GeoDegenerateVerticalLine e
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.addLatitudeZone(topLat).addLatitudeZone(bottomLat)
-        .addLongitudeSlice(longitude, longitude);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.addVerticalPlane(planetModel, longitude, plane, boundingPlane, topPlane, bottomPlane)
+      .addPoint(UHC).addPoint(LHC);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLatitudeZone.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLatitudeZone.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLatitudeZone.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLatitudeZone.java Mon Aug 17 13:45:42 2015
@@ -121,11 +121,10 @@ public class GeoLatitudeZone extends Geo
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.noLongitudeBound().addLatitudeZone(topLat).addLatitudeZone(bottomLat);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.noLongitudeBound(planetModel)
+      .addHorizontalPlane(planetModel, topLat, topPlane)
+      .addHorizontalPlane(planetModel, bottomLat, bottomPlane);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLongitudeSlice.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLongitudeSlice.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLongitudeSlice.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLongitudeSlice.java Mon Aug 17 13:45:42 2015
@@ -129,12 +129,13 @@ public class GeoLongitudeSlice extends G
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.noTopLatitudeBound().noBottomLatitudeBound();
-    bounds.addLongitudeSlice(leftLon, rightLon);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds.noTopLatitudeBound(planetModel).noBottomLatitudeBound(planetModel)
+      .addVerticalPlane(planetModel, leftLon, leftPlane, rightPlane)
+      .addVerticalPlane(planetModel, rightLon, rightPlane, leftPlane)
+      .addPoint(planetModel.NORTH_POLE)
+      .addPoint(planetModel.SOUTH_POLE);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthLatitudeZone.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthLatitudeZone.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthLatitudeZone.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthLatitudeZone.java Mon Aug 17 13:45:42 2015
@@ -100,11 +100,9 @@ public class GeoNorthLatitudeZone extend
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.noLongitudeBound().noTopLatitudeBound().addLatitudeZone(bottomLat);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.noLongitudeBound(planetModel).noTopLatitudeBound(planetModel)
+      .addHorizontalPlane(planetModel, bottomLat, bottomPlane);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthRectangle.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthRectangle.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthRectangle.java Mon Aug 17 13:45:42 2015
@@ -90,8 +90,8 @@ public class GeoNorthRectangle extends G
     final double cosRightLon = Math.cos(rightLon);
 
     // Now build the points
-    this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
-    this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
+    this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon, bottomLat, rightLon);
+    this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon, bottomLat, leftLon);
 
     final double middleLat = (Math.PI * 0.5 + bottomLat) * 0.5;
     final double sinMiddleLat = Math.sin(middleLat);
@@ -176,12 +176,12 @@ public class GeoNorthRectangle extends G
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.noTopLatitudeBound().addLatitudeZone(bottomLat)
-        .addLongitudeSlice(leftLon, rightLon);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.noTopLatitudeBound(planetModel)
+      .addHorizontalPlane(planetModel, bottomLat, bottomPlane, leftPlane, rightPlane)
+      .addVerticalPlane(planetModel, leftLon, leftPlane, bottomPlane, rightPlane)
+      .addVerticalPlane(planetModel, rightLon, rightPlane, bottomPlane, leftPlane)
+      .addPoint(LLHC).addPoint(LRHC);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPath.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPath.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPath.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPath.java Mon Aug 17 13:45:42 2015
@@ -278,8 +278,8 @@ public class GeoPath extends GeoBaseDist
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    bounds = super.getBounds(bounds);
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
     // For building bounds, order matters.  We want to traverse
     // never more than 180 degrees longitude at a pop or we risk having the
     // bounds object get itself inverted.  So do the edges first.
@@ -289,7 +289,6 @@ public class GeoPath extends GeoBaseDist
     for (SegmentEndpoint pathPoint : endPoints) {
       pathPoint.getBounds(planetModel, bounds);
     }
-    return bounds;
   }
 
   @Override
@@ -358,7 +357,7 @@ public class GeoPath extends GeoBaseDist
     public SegmentEndpoint(final GeoPoint point, final GeoPoint upperPoint, final GeoPoint lowerPoint) {
       this.point = point;
       // Construct normal plane
-      final Plane normalPlane = Plane.constructNormalizedVerticalPlane(upperPoint, lowerPoint, point);
+      final Plane normalPlane = Plane.constructNormalizedZPlane(upperPoint, lowerPoint, point);
       // Construct a sided plane that goes through the two points and whose normal is in the normalPlane.
       this.circlePlane = SidedPlane.constructNormalizedPerpendicularSidedPlane(point, normalPlane, upperPoint, lowerPoint);
       this.cutoffPlanes = new Membership[0];
@@ -533,7 +532,7 @@ public class GeoPath extends GeoBaseDist
       bounds.addPoint(point);
       if (circlePlane == null)
         return;
-      circlePlane.recordBounds(planetModel, bounds);
+      bounds.addPlane(planetModel, circlePlane);
     }
 
     @Override
@@ -769,15 +768,11 @@ public class GeoPath extends GeoBaseDist
      */
     public void getBounds(final PlanetModel planetModel, Bounds bounds) {
       // We need to do all bounding planes as well as corner points
-      bounds.addPoint(start).addPoint(end);
-      upperConnectingPlane.recordBounds(planetModel, startCutoffPlane, bounds, lowerConnectingPlane, endCutoffPlane);
-      startCutoffPlane.recordBounds(planetModel, lowerConnectingPlane, bounds, endCutoffPlane, upperConnectingPlane);
-      lowerConnectingPlane.recordBounds(planetModel, endCutoffPlane, bounds, upperConnectingPlane, startCutoffPlane);
-      endCutoffPlane.recordBounds(planetModel, upperConnectingPlane, bounds, startCutoffPlane, lowerConnectingPlane);
-      upperConnectingPlane.recordBounds(planetModel, bounds, lowerConnectingPlane, startCutoffPlane, endCutoffPlane);
-      lowerConnectingPlane.recordBounds(planetModel, bounds, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
-      startCutoffPlane.recordBounds(planetModel, bounds, endCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
-      endCutoffPlane.recordBounds(planetModel, bounds, startCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
+      bounds.addPoint(start).addPoint(end).addPoint(ULHC).addPoint(URHC).addPoint(LRHC).addPoint(LLHC);
+      bounds.addPlane(planetModel, upperConnectingPlane, lowerConnectingPlane, startCutoffPlane, endCutoffPlane);
+      bounds.addPlane(planetModel, lowerConnectingPlane, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
+      bounds.addPlane(planetModel, startCutoffPlane, endCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
+      bounds.addPlane(planetModel, endCutoffPlane, startCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
     }
 
   }

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoRectangle.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoRectangle.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoRectangle.java Mon Aug 17 13:45:42 2015
@@ -112,10 +112,10 @@ public class GeoRectangle extends GeoBas
     final double cosRightLon = Math.cos(rightLon);
 
     // Now build the four points
-    this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
-    this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon);
-    this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
-    this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
+    this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon, topLat, leftLon);
+    this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon, topLat, rightLon);
+    this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon, bottomLat, rightLon);
+    this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon, bottomLat, leftLon);
 
     final double middleLat = (topLat + bottomLat) * 0.5;
     final double sinMiddleLat = Math.sin(middleLat);
@@ -198,12 +198,12 @@ public class GeoRectangle extends GeoBas
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.addLatitudeZone(topLat).addLatitudeZone(bottomLat)
-        .addLongitudeSlice(leftLon, rightLon);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.addHorizontalPlane(planetModel, topLat, topPlane, bottomPlane, leftPlane, rightPlane)
+      .addVerticalPlane(planetModel, rightLon, rightPlane, topPlane, bottomPlane, leftPlane)
+      .addHorizontalPlane(planetModel, bottomLat, bottomPlane, topPlane, leftPlane, rightPlane)
+      .addVerticalPlane(planetModel, leftLon, leftPlane, topPlane, bottomPlane, rightPlane)
+      .addPoint(ULHC).addPoint(URHC).addPoint(LLHC).addPoint(LRHC);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoShape.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoShape.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoShape.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoShape.java Mon Aug 17 13:45:42 2015
@@ -54,14 +54,11 @@ public interface GeoShape extends Member
   public boolean intersects(final Plane plane, final GeoPoint[] notablePoints, final Membership... bounds);
 
   /**
-   * Compute longitude/latitude bounds for the shape.
+   * Compute 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.
+   * @param bounds is the input bounds object.
+   *             The input object will be modified.
    */
-  public Bounds getBounds(final Bounds bounds);
+  public void getBounds(final Bounds bounds);
 
 }

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthLatitudeZone.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthLatitudeZone.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthLatitudeZone.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthLatitudeZone.java Mon Aug 17 13:45:42 2015
@@ -102,21 +102,10 @@ public class GeoSouthLatitudeZone extend
     return p.intersects(planetModel, topPlane, 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)
-      bounds = new Bounds();
-    bounds.noLongitudeBound().addLatitudeZone(topLat).noBottomLatitudeBound();
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.noLongitudeBound(planetModel).noBottomLatitudeBound(planetModel)
+      .addHorizontalPlane(planetModel, topLat, topPlane);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthRectangle.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthRectangle.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthRectangle.java Mon Aug 17 13:45:42 2015
@@ -94,8 +94,8 @@ public class GeoSouthRectangle extends G
     final double cosRightLon = Math.cos(rightLon);
 
     // Now build the four points
-    this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
-    this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon);
+    this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon, topLat, leftLon);
+    this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon, topLat, rightLon);
 
     final double middleLat = (topLat - Math.PI * 0.5) * 0.5;
     final double sinMiddleLat = Math.sin(middleLat);
@@ -174,12 +174,12 @@ public class GeoSouthRectangle extends G
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.addLatitudeZone(topLat).noBottomLatitudeBound()
-        .addLongitudeSlice(leftLon, rightLon);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.noBottomLatitudeBound(planetModel)
+      .addHorizontalPlane(planetModel, topLat, topPlane, leftPlane, rightPlane)
+      .addVerticalPlane(planetModel, leftLon, leftPlane, topPlane, rightPlane)
+      .addVerticalPlane(planetModel, rightLon, rightPlane, topPlane, leftPlane)
+      .addPoint(URHC).addPoint(ULHC);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideDegenerateHorizontalLine.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideDegenerateHorizontalLine.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideDegenerateHorizontalLine.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideDegenerateHorizontalLine.java Mon Aug 17 13:45:42 2015
@@ -90,8 +90,8 @@ public class GeoWideDegenerateHorizontal
     final double cosRightLon = Math.cos(rightLon);
 
     // Now build the two points
-    this.LHC = new GeoPoint(planetModel, sinLatitude, sinLeftLon, cosLatitude, cosLeftLon);
-    this.RHC = new GeoPoint(planetModel, sinLatitude, sinRightLon, cosLatitude, cosRightLon);
+    this.LHC = new GeoPoint(planetModel, sinLatitude, sinLeftLon, cosLatitude, cosLeftLon, latitude, leftLon);
+    this.RHC = new GeoPoint(planetModel, sinLatitude, sinRightLon, cosLatitude, cosRightLon, latitude, rightLon);
 
     this.plane = new Plane(planetModel, sinLatitude);
 
@@ -167,12 +167,11 @@ public class GeoWideDegenerateHorizontal
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.addLatitudeZone(latitude)
-        .addLongitudeSlice(leftLon, rightLon);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.isWide(planetModel)
+      .addHorizontalPlane(planetModel, latitude, plane, eitherBound)
+      .addPoint(LHC)
+      .addPoint(RHC);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideLongitudeSlice.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideLongitudeSlice.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideLongitudeSlice.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideLongitudeSlice.java Mon Aug 17 13:45:42 2015
@@ -135,12 +135,12 @@ public class GeoWideLongitudeSlice exten
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.noTopLatitudeBound().noBottomLatitudeBound();
-    bounds.addLongitudeSlice(leftLon, rightLon);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.isWide(planetModel).noTopLatitudeBound(planetModel).noBottomLatitudeBound(planetModel)
+      .addVerticalPlane(planetModel, leftLon, leftPlane)
+      .addVerticalPlane(planetModel, rightLon, rightPlane)
+      .addPoint(planetModel.NORTH_POLE)
+      .addPoint(planetModel.SOUTH_POLE);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideNorthRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideNorthRectangle.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideNorthRectangle.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideNorthRectangle.java Mon Aug 17 13:45:42 2015
@@ -94,8 +94,8 @@ public class GeoWideNorthRectangle exten
     final double cosRightLon = Math.cos(rightLon);
 
     // Now build the four points
-    this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
-    this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
+    this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon, bottomLat, rightLon);
+    this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon, bottomLat, leftLon);
 
     final double middleLat = (Math.PI * 0.5 + bottomLat) * 0.5;
     final double sinMiddleLat = Math.sin(middleLat);
@@ -178,12 +178,12 @@ public class GeoWideNorthRectangle exten
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.noTopLatitudeBound().addLatitudeZone(bottomLat)
-        .addLongitudeSlice(leftLon, rightLon);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.isWide(planetModel).noTopLatitudeBound(planetModel)
+      .addHorizontalPlane(planetModel, bottomLat, bottomPlane, eitherBound)
+      .addVerticalPlane(planetModel, leftLon, leftPlane, bottomPlane)
+      .addVerticalPlane(planetModel, rightLon, rightPlane, bottomPlane)
+      .addPoint(LLHC).addPoint(LRHC);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideRectangle.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideRectangle.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideRectangle.java Mon Aug 17 13:45:42 2015
@@ -111,10 +111,10 @@ public class GeoWideRectangle extends Ge
     final double cosRightLon = Math.cos(rightLon);
 
     // Now build the four points
-    this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
-    this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon);
-    this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
-    this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
+    this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon, topLat, leftLon);
+    this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon, topLat, rightLon);
+    this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon, bottomLat, rightLon);
+    this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon, bottomLat, leftLon);
 
     final double middleLat = (topLat + bottomLat) * 0.5;
     final double sinMiddleLat = Math.sin(middleLat);
@@ -206,12 +206,13 @@ public class GeoWideRectangle extends Ge
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.addLatitudeZone(topLat).addLatitudeZone(bottomLat)
-        .addLongitudeSlice(leftLon, rightLon);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.isWide(planetModel)
+      .addHorizontalPlane(planetModel, topLat, topPlane, bottomPlane, eitherBound)
+      .addVerticalPlane(planetModel, rightLon, rightPlane, topPlane, bottomPlane)
+      .addHorizontalPlane(planetModel, bottomLat, bottomPlane, topPlane, eitherBound)
+      .addVerticalPlane(planetModel, leftLon, leftPlane, topPlane, bottomPlane)
+      .addPoint(ULHC).addPoint(URHC).addPoint(LRHC).addPoint(LLHC);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideSouthRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideSouthRectangle.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideSouthRectangle.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideSouthRectangle.java Mon Aug 17 13:45:42 2015
@@ -94,8 +94,8 @@ public class GeoWideSouthRectangle exten
     final double cosRightLon = Math.cos(rightLon);
 
     // Now build the four points
-    this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
-    this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon);
+    this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon, topLat, leftLon);
+    this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon, topLat, rightLon);
 
     final double middleLat = (topLat - Math.PI * 0.5) * 0.5;
     final double sinMiddleLat = Math.sin(middleLat);
@@ -177,12 +177,12 @@ public class GeoWideSouthRectangle exten
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.addLatitudeZone(topLat).noBottomLatitudeBound()
-        .addLongitudeSlice(leftLon, rightLon);
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.isWide(planetModel).noBottomLatitudeBound(planetModel)
+      .addHorizontalPlane(planetModel, topLat, topPlane, eitherBound)
+      .addVerticalPlane(planetModel, rightLon, rightPlane, topPlane)
+      .addVerticalPlane(planetModel, leftLon, leftPlane, topPlane)
+      .addPoint(ULHC).addPoint(URHC);
   }
 
   @Override

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWorld.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWorld.java?rev=1696275&r1=1696274&r2=1696275&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWorld.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWorld.java Mon Aug 17 13:45:42 2015
@@ -68,11 +68,8 @@ public class GeoWorld extends GeoBaseBBo
   }
 
   @Override
-  public Bounds getBounds(Bounds bounds) {
-    if (bounds == null)
-      bounds = new Bounds();
-    bounds.noLongitudeBound().noTopLatitudeBound().noBottomLatitudeBound();
-    return bounds;
+  public void getBounds(Bounds bounds) {
+    bounds.noLongitudeBound(planetModel).noTopLatitudeBound(planetModel).noBottomLatitudeBound(planetModel);
   }
 
   @Override

Added: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LatLonBounds.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LatLonBounds.java?rev=1696275&view=auto
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LatLonBounds.java (added)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LatLonBounds.java Mon Aug 17 13:45:42 2015
@@ -0,0 +1,370 @@
+package org.apache.lucene.geo3d;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * An object for accumulating latitude/longitude bounds information.
+ *
+ * @lucene.experimental
+ */
+public class LatLonBounds implements Bounds {
+
+  /** Set to true if no longitude bounds can be stated */
+  protected boolean noLongitudeBound = false;
+  /** Set to true if no top latitude bound can be stated */
+  protected boolean noTopLatitudeBound = false;
+  /** Set to true if no bottom latitude bound can be stated */
+  protected boolean noBottomLatitudeBound = false;
+
+  /** If non-null, the minimum latitude bound */
+  protected Double minLatitude = null;
+  /** If non-null, the maximum latitude bound */
+  protected Double maxLatitude = null;
+
+  // For longitude bounds, this class needs to worry about keeping track of the distinction
+  // between left-side bounds and right-side bounds.  Points are always submitted in pairs
+  // which have a maximum longitude separation of Math.PI.  It's therefore always possible
+  // to determine which point represents a left bound, and which point represents a right
+  // bound.
+  //
+  // The next problem is how to compare two of the same kind of bound, e.g. two left bounds.
+  // We need to keep track of the leftmost longitude of the shape, but since this is a circle,
+  // this is arbitrary.  What we could try to do instead would be to find a pair of (left,right) bounds such
+  // that:
+  // (1) all other bounds are within, and
+  // (2) the left minus right distance is minimized
+  // Unfortunately, there are still shapes that cannot be summarized in this way correctly.
+  // For example. consider a spiral that entirely circles the globe; we might arbitrarily choose
+  // lat/lon bounds that do not in fact circle the globe.
+  //
+  // One way to handle the longitude issue correctly is therefore to stipulate that we
+  // walk the bounds of the shape in some kind of connected order.  Each point or circle is therefore
+  // added in a sequence.  We also need an interior point to make sure we have the right
+  // choice of longitude bounds.  But even with this, we still can't always choose whether the actual shape
+  // goes right or left.
+  //
+  // We can make the specification truly general by submitting the following in order:
+  // addSide(PlaneSide side, Membership... constraints)
+  // ...
+  // This is unambiguous, but I still can't see yet how this would help compute the bounds.  The plane
+  // solution would in general seem to boil down to the same logic that relies on points along the path
+  // to define the shape boundaries.  I guess the one thing that you do know for a bounded edge is that
+  // the endpoints are actually connected.  But it is not clear whether relationship helps in any way.
+  //
+  // In any case, if we specify shapes by a sequence of planes, we should stipulate that multiple sequences
+  // are allowed, provided they progressively tile an area of the sphere that is connected and sequential.
+  // For example, paths do alternating rectangles and circles, in sequence.  Each sequence member is
+  // described by a sequence of planes.  I think it would also be reasonable to insist that the first segment
+  // of a shape overlap or adjoin the previous shape.
+  //
+  // Here's a way to think about it that might help: Traversing every edge should grow the longitude bounds
+  // in the direction of the traversal.  So if the traversal is always known to be less than PI in total longitude
+  // angle, then it is possible to use the endpoints to determine the unambiguous extension of the envelope.
+  // For example, say you are currently at longitude -0.5.  The next point is at longitude PI-0.1.  You could say
+  // that the difference in longitude going one way around would be beter than the distance the other way
+  // around, and therefore the longitude envelope should be extended accordingly.  But in practice, when an
+  // edge goes near a pole and may be inclined as well, the longer longitude change might be the right path, even
+  // if the arc length is short.  So this too doesn't work.
+  //
+  // Given we have a hard time making an exact match, here's the current proposal.  The proposal is a
+  // heuristic, based on the idea that most areas are small compared to the circumference of the globe.
+  // We keep track of the last point we saw, and take each point as it arrives, and compute its longitude.
+  // Then, we have a choice as to which way to expand the envelope: we can expand by going to the left or
+  // to the right.  We choose the direction with the least longitude difference.  (If we aren't sure,
+  // and can recognize that, we can set "unconstrained in longitude".)
+
+  /** If non-null, the left longitude bound */
+  protected Double leftLongitude = null;
+  /** If non-null, the right longitude bound */
+  protected Double rightLongitude = null;
+
+  /** Construct an empty bounds object */
+  public LatLonBounds() {
+  }
+
+  // Accessor methods
+  
+  /** Get maximum latitude, if any.
+   *@return maximum latitude or null.
+   */
+  public Double getMaxLatitude() {
+    return maxLatitude;
+  }
+
+  /** Get minimum latitude, if any.
+   *@return minimum latitude or null.
+   */
+  public Double getMinLatitude() {
+    return minLatitude;
+  }
+
+  /** Get left longitude, if any.
+   *@return left longitude, or null.
+   */
+  public Double getLeftLongitude() {
+    return leftLongitude;
+  }
+
+  /** Get right longitude, if any.
+   *@return right longitude, or null.
+   */
+  public Double getRightLongitude() {
+    return rightLongitude;
+  }
+
+  // Degenerate case check
+  
+  /** Check if there's no longitude bound.
+   *@return true if no longitude bound.
+   */
+  public boolean checkNoLongitudeBound() {
+    return noLongitudeBound;
+  }
+
+  /** Check if there's no top latitude bound.
+   *@return true if no top latitude bound.
+   */
+  public boolean checkNoTopLatitudeBound() {
+    return noTopLatitudeBound;
+  }
+
+  /** Check if there's no bottom latitude bound.
+   *@return true if no bottom latitude bound.
+   */
+  public boolean checkNoBottomLatitudeBound() {
+    return noBottomLatitudeBound;
+  }
+
+  // Modification methods
+  
+  @Override
+  public Bounds addPlane(final PlanetModel planetModel, final Plane plane, final Membership... bounds) {
+    plane.recordBounds(planetModel, this, bounds);
+    return this;
+  }
+
+  @Override
+  public Bounds addHorizontalPlane(final PlanetModel planetModel,
+    final double latitude,
+    final Plane horizontalPlane,
+    final Membership... bounds) {
+    if (!noTopLatitudeBound || !noBottomLatitudeBound) {
+      addLatitudeBound(latitude);
+    }
+    return this;
+  }
+    
+  @Override
+  public Bounds addVerticalPlane(final PlanetModel planetModel,
+    final double longitude,
+    final Plane verticalPlane,
+    final Membership... bounds) {
+    if (!noLongitudeBound) {
+      addLongitudeBound(longitude);
+    }
+    return this;
+  }
+
+  @Override
+  public Bounds isWide(final PlanetModel planetModel) {
+    return noLongitudeBound(planetModel);
+  }
+
+  @Override
+  public Bounds addXValue(final GeoPoint point) {
+    if (!noLongitudeBound) {
+      // Get a longitude value
+      addLongitudeBound(point.getLongitude());
+    }
+    return this;
+  }
+
+  @Override
+  public Bounds addYValue(final GeoPoint point) {
+    if (!noLongitudeBound) {
+      // Get a longitude value
+      addLongitudeBound(point.getLongitude());
+    }
+    return this;
+  }
+
+  @Override
+  public Bounds addZValue(final GeoPoint point) {
+    if (!noTopLatitudeBound || !noBottomLatitudeBound) {
+      // Compute a latitude value
+      double latitude = point.getLatitude();
+      addLatitudeBound(latitude);
+    }
+    return this;
+  }
+
+  @Override
+  public Bounds addPoint(GeoPoint point) {
+    if (!noLongitudeBound) {
+      // Get a longitude value
+      addLongitudeBound(point.getLongitude());
+    }
+    if (!noTopLatitudeBound || !noBottomLatitudeBound) {
+      // Compute a latitude value
+      addLatitudeBound(point.getLatitude());
+    }
+    return this;
+  }
+  
+  @Override
+  public Bounds noLongitudeBound(final PlanetModel planetModel) {
+    noLongitudeBound = true;
+    leftLongitude = null;
+    rightLongitude = null;
+    return this;
+  }
+
+  @Override
+  public Bounds noTopLatitudeBound(final PlanetModel planetModel) {
+    noTopLatitudeBound = true;
+    maxLatitude = null;
+    return this;
+  }
+
+  @Override
+  public Bounds noBottomLatitudeBound(final PlanetModel planetModel) {
+    noBottomLatitudeBound = true;
+    minLatitude = null;
+    return this;
+  }
+
+  // Protected methods
+  
+  /** Update latitude bound.
+   *@param latitude is the latitude.
+   */
+  protected void addLatitudeBound(double latitude) {
+    if (!noTopLatitudeBound && (maxLatitude == null || latitude > maxLatitude))
+      maxLatitude = latitude;
+    if (!noBottomLatitudeBound && (minLatitude == null || latitude < minLatitude))
+      minLatitude = latitude;
+  }
+
+  /** Update longitude bound.
+   *@param newLeftLongitude is the left longitude.
+   *@param newRightLongitude is the right longitude.
+   */
+  protected void addLongitudeBound(double newLeftLongitude, double newRightLongitude) {
+    if (leftLongitude == null && rightLongitude == null) {
+      leftLongitude = newLeftLongitude;
+      rightLongitude = newRightLongitude;
+    } else {
+      // Map the current range to something monotonically increasing
+      double currentLeftLongitude = leftLongitude;
+      double currentRightLongitude = rightLongitude;
+      if (currentRightLongitude < currentLeftLongitude)
+        currentRightLongitude += 2.0 * Math.PI;
+      double adjustedLeftLongitude = newLeftLongitude;
+      double adjustedRightLongitude = newRightLongitude;
+      if (adjustedRightLongitude < adjustedLeftLongitude)
+        adjustedRightLongitude += 2.0 * Math.PI;
+      // Compare to see what the relationship is
+      if (currentLeftLongitude <= adjustedLeftLongitude && currentRightLongitude >= adjustedRightLongitude) {
+        // No adjustment needed.
+      } else if (currentLeftLongitude >= adjustedLeftLongitude && currentRightLongitude <= adjustedRightLongitude) {
+        // New longitude entirely contains old one
+        leftLongitude = newLeftLongitude;
+        rightLongitude = newRightLongitude;
+      } else {
+        if (currentLeftLongitude > adjustedLeftLongitude) {
+          // New left longitude needed
+          leftLongitude = newLeftLongitude;
+        }
+        if (currentRightLongitude < adjustedRightLongitude) {
+          // New right longitude needed
+          rightLongitude = newRightLongitude;
+        }
+      }
+    }
+    double testRightLongitude = rightLongitude;
+    if (testRightLongitude < leftLongitude)
+      testRightLongitude += Math.PI * 2.0;
+    // If the bound exceeds 180 degrees, we know we could have screwed up.
+    if (testRightLongitude - leftLongitude >= Math.PI) {
+      noLongitudeBound = true;
+      leftLongitude = null;
+      rightLongitude = null;
+    }
+  }
+
+  /** Update longitude bound.
+   *@param longitude is the new longitude value.
+   */
+  protected void addLongitudeBound(double longitude) {
+    // If this point is within the current bounds, we're done; otherwise
+    // expand one side or the other.
+    if (leftLongitude == null && rightLongitude == null) {
+      leftLongitude = longitude;
+      rightLongitude = longitude;
+    } else {
+      // Compute whether we're to the right of the left value.  But the left value may be greater than
+      // the right value.
+      double currentLeftLongitude = leftLongitude;
+      double currentRightLongitude = rightLongitude;
+      if (currentRightLongitude < currentLeftLongitude)
+        currentRightLongitude += 2.0 * Math.PI;
+      // We have a range to look at that's going in the right way.
+      // Now, do the same trick with the computed longitude.
+      if (longitude < currentLeftLongitude)
+        longitude += 2.0 * Math.PI;
+
+      if (longitude < currentLeftLongitude || longitude > currentRightLongitude) {
+        // Outside of current bounds.  Consider carefully how we'll expand.
+        double leftExtensionAmt;
+        double rightExtensionAmt;
+        if (longitude < currentLeftLongitude) {
+          leftExtensionAmt = currentLeftLongitude - longitude;
+        } else {
+          leftExtensionAmt = currentLeftLongitude + 2.0 * Math.PI - longitude;
+        }
+        if (longitude > currentRightLongitude) {
+          rightExtensionAmt = longitude - currentRightLongitude;
+        } else {
+          rightExtensionAmt = longitude + 2.0 * Math.PI - currentRightLongitude;
+        }
+        if (leftExtensionAmt < rightExtensionAmt) {
+          currentLeftLongitude = leftLongitude - leftExtensionAmt;
+          while (currentLeftLongitude <= -Math.PI) {
+            currentLeftLongitude += 2.0 * Math.PI;
+          }
+          leftLongitude = currentLeftLongitude;
+        } else {
+          currentRightLongitude = rightLongitude + rightExtensionAmt;
+          while (currentRightLongitude > Math.PI) {
+            currentRightLongitude -= 2.0 * Math.PI;
+          }
+          rightLongitude = currentRightLongitude;
+        }
+      }
+    }
+    double testRightLongitude = rightLongitude;
+    if (testRightLongitude < leftLongitude)
+      testRightLongitude += Math.PI * 2.0;
+    if (testRightLongitude - leftLongitude >= Math.PI) {
+      noLongitudeBound = true;
+      leftLongitude = null;
+      rightLongitude = null;
+    }
+  }
+
+}