You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by no...@apache.org on 2016/03/09 17:00:12 UTC

[01/50] [abbrv] lucene-solr git commit: fix smoke tester to understand newly old index

Repository: lucene-solr
Updated Branches:
  refs/heads/apiv2 943f2709a -> ec4889a2b


fix smoke tester to understand newly old index


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

Branch: refs/heads/apiv2
Commit: 9617d3d400ea4d6b3e00cf0b3a2c94598647bb4e
Parents: 9082d5f
Author: Mike McCandless <mi...@apache.org>
Authored: Mon Mar 7 10:38:04 2016 -0500
Committer: Mike McCandless <mi...@apache.org>
Committed: Mon Mar 7 10:38:04 2016 -0500

----------------------------------------------------------------------
 dev-tools/scripts/smokeTestRelease.py | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9617d3d4/dev-tools/scripts/smokeTestRelease.py
----------------------------------------------------------------------
diff --git a/dev-tools/scripts/smokeTestRelease.py b/dev-tools/scripts/smokeTestRelease.py
index aa367f6..87a772f 100644
--- a/dev-tools/scripts/smokeTestRelease.py
+++ b/dev-tools/scripts/smokeTestRelease.py
@@ -1306,6 +1306,8 @@ def confirmAllReleasesAreTestedForBackCompat(smokeVersion, unpackPath):
       # Mixed version test case; ignore it for our purposes because we only
       # tally up the "tests single Lucene version" indices
       continue
+    elif name == '5.0.0.singlesegment':
+      tup = 5, 0, 0
     else:
       raise RuntimeError('could not parse version %s' % name)
 


[21/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPath.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPath.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPath.java
deleted file mode 100755
index bc5b9cf..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPath.java
+++ /dev/null
@@ -1,797 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 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 GeoBaseDistanceShape {
-  /** The cutoff angle (width) */
-  protected final double cutoffAngle;
-
-  /** Sine of cutoff angle */
-  protected final double sinAngle;
-  /** Cosine of cutoff angle */
-  protected final double cosAngle;
-
-  /** The original list of path points */
-  protected final List<GeoPoint> points = new ArrayList<GeoPoint>();
-  
-  /** A list of SegmentEndpoints */
-  protected List<SegmentEndpoint> endPoints;
-  /** A list of PathSegments */
-  protected List<PathSegment> segments;
-
-  /** A point on the edge */
-  protected GeoPoint[] edgePoints;
-
-  /** Set to true if path has been completely constructed */
-  protected boolean isDone = false;
-  
-  /** Constructor.
-   *@param planetModel is the planet model.
-   *@param maxCutoffAngle is the width of the path, measured as an angle.
-   *@param pathPoints are the points in the path.
-   */
-  public GeoPath(final PlanetModel planetModel, final double maxCutoffAngle, final GeoPoint[] pathPoints) {
-    this(planetModel, maxCutoffAngle);
-    Collections.addAll(points, pathPoints);
-    done();
-  }
-  
-  /** Piece-wise constructor.  Use in conjunction with addPoint() and done().
-   *@param planetModel is the planet model.
-   *@param maxCutoffAngle is the width of the path, measured as an angle.
-   */
-  public GeoPath(final PlanetModel planetModel, final double maxCutoffAngle) {
-    super(planetModel);
-    if (maxCutoffAngle <= 0.0 || maxCutoffAngle > Math.PI * 0.5)
-      throw new IllegalArgumentException("Cutoff angle out of bounds");
-    this.cutoffAngle = maxCutoffAngle;
-    this.cosAngle = Math.cos(maxCutoffAngle);
-    this.sinAngle = Math.sin(maxCutoffAngle);
-  }
-
-  /** Add a point to the path.
-   *@param lat is the latitude of the point.
-   *@param lon is the longitude of the point.
-   */
-  public void addPoint(final double lat, final double lon) {
-    if (isDone)
-      throw new IllegalStateException("Can't call addPoint() if done() already called");
-    points.add(new GeoPoint(planetModel, lat, lon));
-  }
-  
-  /** Complete the path.
-   */
-  public void done() {
-    if (isDone)
-      throw new IllegalStateException("Can't call done() twice");
-    if (points.size() == 0)
-      throw new IllegalArgumentException("Path must have at least one point");
-    isDone = true;
-
-    endPoints = new ArrayList<>(points.size());
-    segments = new ArrayList<>(points.size());
-    // Compute an offset to use for all segments.  This will be based on the minimum magnitude of
-    // the entire ellipsoid.
-    final double cutoffOffset = this.sinAngle * planetModel.getMinimumMagnitude();
-    
-    // First, build all segments.  We'll then go back and build corresponding segment endpoints.
-    GeoPoint lastPoint = null;
-    for (final GeoPoint end : points) {
-      if (lastPoint != null) {
-        final Plane normalizedConnectingPlane = new Plane(lastPoint, end);
-        if (normalizedConnectingPlane == null) {
-          continue;
-        }
-        segments.add(new PathSegment(planetModel, lastPoint, end, normalizedConnectingPlane, cutoffOffset));
-      }
-      lastPoint = end;
-    }
-    
-    if (segments.size() == 0) {
-      // Simple circle
-      double lat = points.get(0).getLatitude();
-      double lon = points.get(0).getLongitude();
-      // Compute two points on the circle, with the right angle from the center.  We'll use these
-      // to obtain the perpendicular plane to the circle.
-      double upperLat = lat + cutoffAngle;
-      double upperLon = lon;
-      if (upperLat > Math.PI * 0.5) {
-        upperLon += Math.PI;
-        if (upperLon > Math.PI)
-          upperLon -= 2.0 * Math.PI;
-        upperLat = Math.PI - upperLat;
-      }
-      double lowerLat = lat - cutoffAngle;
-      double lowerLon = lon;
-      if (lowerLat < -Math.PI * 0.5) {
-        lowerLon += Math.PI;
-        if (lowerLon > Math.PI)
-          lowerLon -= 2.0 * Math.PI;
-        lowerLat = -Math.PI - lowerLat;
-      }
-      final GeoPoint upperPoint = new GeoPoint(planetModel, upperLat, upperLon);
-      final GeoPoint lowerPoint = new GeoPoint(planetModel, lowerLat, lowerLon);
-      final GeoPoint point = points.get(0);
-      
-      // Construct normal plane
-      final Plane normalPlane = Plane.constructNormalizedZPlane(upperPoint, lowerPoint, point);
-
-      final SegmentEndpoint onlyEndpoint = new SegmentEndpoint(point, normalPlane, upperPoint, lowerPoint);
-      endPoints.add(onlyEndpoint);
-      this.edgePoints = new GeoPoint[]{onlyEndpoint.circlePlane.getSampleIntersectionPoint(planetModel, normalPlane)};
-      return;
-    }
-    
-    // Create segment endpoints.  Use an appropriate constructor for the start and end of the path.
-    for (int i = 0; i < segments.size(); i++) {
-      final PathSegment currentSegment = segments.get(i);
-      
-      if (i == 0) {
-        // Starting endpoint
-        final SegmentEndpoint startEndpoint = new SegmentEndpoint(currentSegment.start, 
-          currentSegment.startCutoffPlane, currentSegment.ULHC, currentSegment.LLHC);
-        endPoints.add(startEndpoint);
-        this.edgePoints = new GeoPoint[]{currentSegment.ULHC};
-        continue;
-      }
-      
-      // General intersection case
-      final PathSegment prevSegment = segments.get(i-1);
-      // We construct four separate planes, and evaluate which one includes all interior points with least overlap
-      final SidedPlane candidate1 = SidedPlane.constructNormalizedThreePointSidedPlane(currentSegment.start, prevSegment.URHC, currentSegment.ULHC, currentSegment.LLHC);
-      final SidedPlane candidate2 = SidedPlane.constructNormalizedThreePointSidedPlane(currentSegment.start, currentSegment.ULHC, currentSegment.LLHC, prevSegment.LRHC);
-      final SidedPlane candidate3 = SidedPlane.constructNormalizedThreePointSidedPlane(currentSegment.start, currentSegment.LLHC, prevSegment.LRHC, prevSegment.URHC);
-      final SidedPlane candidate4 = SidedPlane.constructNormalizedThreePointSidedPlane(currentSegment.start, prevSegment.LRHC, prevSegment.URHC, currentSegment.ULHC);
-
-      if (candidate1 == null && candidate2 == null && candidate3 == null && candidate4 == null) {
-        // The planes are identical.  We wouldn't need a circle at all except for the possibility of
-        // backing up, which is hard to detect here.
-        final SegmentEndpoint midEndpoint = new SegmentEndpoint(currentSegment.start, 
-          prevSegment.endCutoffPlane, currentSegment.startCutoffPlane, currentSegment.ULHC, currentSegment.LLHC);
-        //don't need a circle at all.  Special constructor...
-        endPoints.add(midEndpoint);
-      } else {
-        endPoints.add(new SegmentEndpoint(currentSegment.start,
-          prevSegment.endCutoffPlane, currentSegment.startCutoffPlane,
-          prevSegment.URHC, prevSegment.LRHC,
-          currentSegment.ULHC, currentSegment.LLHC,
-          candidate1, candidate2, candidate3, candidate4));
-      }
-    }
-    // Do final endpoint
-    final PathSegment lastSegment = segments.get(segments.size()-1);
-    endPoints.add(new SegmentEndpoint(lastSegment.end,
-      lastSegment.endCutoffPlane, lastSegment.URHC, lastSegment.LRHC));
-
-  }
-
-  @Override
-  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(planetModel, distanceStyle, x,y,z);
-      if (distance != Double.MAX_VALUE)
-        return currentDistance + distance;
-      currentDistance += segment.fullPathDistance(distanceStyle);
-    }
-
-    int segmentIndex = 0;
-    currentDistance = 0.0;
-    for (SegmentEndpoint endpoint : endPoints) {
-      double distance = endpoint.pathDistance(distanceStyle, x, y, z);
-      if (distance != Double.MAX_VALUE)
-        return currentDistance + distance;
-      if (segmentIndex < segments.size())
-        currentDistance += segments.get(segmentIndex++).fullPathDistance(distanceStyle);
-    }
-
-    return Double.MAX_VALUE;
-  }
-
-  @Override
-  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
-    double minDistance = Double.MAX_VALUE;
-    for (final SegmentEndpoint endpoint : endPoints) {
-      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;
-    }
-    return minDistance;
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    for (SegmentEndpoint pathPoint : endPoints) {
-      if (pathPoint.isWithin(x, y, z))
-        return true;
-    }
-    for (PathSegment pathSegment : segments) {
-      if (pathSegment.isWithin(x, y, z))
-        return true;
-    }
-    return false;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane plane, final GeoPoint[] notablePoints, final Membership... bounds) {
-    // We look for an intersection with any of the exterior edges of the path.
-    // We also have to look for intersections with the cones described by the endpoints.
-    // Return "true" if any such intersections are found.
-
-    // For plane intersections, the basic idea is to come up with an equation of the line that is
-    // the intersection (if any).  Then, find the intersections with the unit sphere (if any).  If
-    // any of the intersection points are within the bounds, then we've detected an intersection.
-    // Well, sort of.  We can detect intersections also due to overlap of segments with each other.
-    // But that's an edge case and we won't be optimizing for it.
-    //System.err.println(" Looking for intersection of plane "+plane+" with path "+this);
-    for (final SegmentEndpoint pathPoint : endPoints) {
-      if (pathPoint.intersects(planetModel, plane, notablePoints, bounds)) {
-        return true;
-      }
-    }
-
-    for (final PathSegment pathSegment : segments) {
-      if (pathSegment.intersects(planetModel, plane, notablePoints, bounds)) {
-        return true;
-      }
-    }
-
-    return false;
-  }
-
-  @Override
-  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.
-    for (PathSegment pathSegment : segments) {
-      pathSegment.getBounds(planetModel, bounds);
-    }
-    for (SegmentEndpoint pathPoint : endPoints) {
-      pathPoint.getBounds(planetModel, bounds);
-    }
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof GeoPath))
-      return false;
-    GeoPath p = (GeoPath) o;
-    if (!super.equals(p))
-      return false;
-    if (cutoffAngle != p.cutoffAngle)
-      return false;
-    return points.equals(p.points);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    long temp = Double.doubleToLongBits(cutoffAngle);
-    result = 31 * result + (int) (temp ^ (temp >>> 32));
-    result = 31 * result + points.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoPath: {planetmodel=" + planetModel+", width=" + cutoffAngle + "(" + cutoffAngle * 180.0 / Math.PI + "), points={" + points + "}}";
-  }
-
-  /**
-   * This is precalculated data for segment endpoint.
-   * Note well: This is not necessarily a circle.  There are four cases:
-   * (1) The path consists of a single endpoint.  In this case, we build a simple circle with the proper cutoff offset.
-   * (2) This is the end of a path.  The circle plane must be constructed to go through two supplied points and be perpendicular to a connecting plane.
-   * (2.5) Intersection, but the path on both sides is linear.  We generate a circle, but we use the cutoff planes to limit its influence in the straight line case.
-   * (3) This is an intersection in a path.  We are supplied FOUR planes.  If there are intersections within bounds for both upper and lower, then
-   *    we generate no circle at all.  If there is one intersection only, then we generate a plane that includes that intersection, as well as the remaining
-   *    cutoff plane/edge plane points.
-   */
-  public static class SegmentEndpoint {
-    /** The center point of the endpoint */
-    public final GeoPoint point;
-    /** A plane describing the circle */
-    public final SidedPlane circlePlane;
-    /** Pertinent cutoff planes from adjoining segments */
-    public final Membership[] cutoffPlanes;
-    /** Notable points for this segment endpoint */
-    public final GeoPoint[] notablePoints;
-    /** No notable points from the circle itself */
-    public final static GeoPoint[] circlePoints = new GeoPoint[0];
-    /** Null membership */
-    public final static Membership[] NO_MEMBERSHIP = new Membership[0];
-    
-    /** Base case.  Does nothing at all.
-     */
-    public SegmentEndpoint(final GeoPoint point) {
-      this.point = point;
-      this.circlePlane = null;
-      this.cutoffPlanes = null;
-      this.notablePoints = null;
-    }
-    
-    /** Constructor for case (1).
-     * Generate a simple circle cutoff plane.
-     *@param point is the center point.
-     *@param upperPoint is a point that must be on the circle plane.
-     *@param lowerPoint is another point that must be on the circle plane.
-     */
-    public SegmentEndpoint(final GeoPoint point, final Plane normalPlane, final GeoPoint upperPoint, final GeoPoint lowerPoint) {
-      this.point = 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 = NO_MEMBERSHIP;
-      this.notablePoints = circlePoints;
-    }
-    
-    /** Constructor for case (2).
-     * Generate an endpoint, given a single cutoff plane plus upper and lower edge points.
-     *@param point is the center point.
-     *@param cutoffPlane is the plane from the adjoining path segment marking the boundary between this endpoint and that segment.
-     *@param topEdgePoint is a point on the cutoffPlane that should be also on the circle plane.
-     *@param bottomEdgePoint is another point on the cutoffPlane that should be also on the circle plane.
-     */
-    public SegmentEndpoint(final GeoPoint point,
-      final SidedPlane cutoffPlane, final GeoPoint topEdgePoint, final GeoPoint bottomEdgePoint) {
-      this.point = point;
-      this.cutoffPlanes = new Membership[]{new SidedPlane(cutoffPlane)};
-      this.notablePoints = new GeoPoint[]{topEdgePoint, bottomEdgePoint};
-      // To construct the plane, we now just need D, which is simply the negative of the evaluation of the circle normal vector at one of the points.
-      this.circlePlane = SidedPlane.constructNormalizedPerpendicularSidedPlane(point, cutoffPlane, topEdgePoint, bottomEdgePoint);
-    }
-
-    /** Constructor for case (2.5).
-     * Generate an endpoint, given two cutoff planes plus upper and lower edge points.
-     *@param point is the center.
-     *@param cutoffPlane1 is one adjoining path segment cutoff plane.
-     *@param cutoffPlane2 is another adjoining path segment cutoff plane.
-     *@param topEdgePoint is a point on the cutoffPlane that should be also on the circle plane.
-     *@param bottomEdgePoint is another point on the cutoffPlane that should be also on the circle plane.
-     */
-    public SegmentEndpoint(final GeoPoint point,
-      final SidedPlane cutoffPlane1, final SidedPlane cutoffPlane2, final GeoPoint topEdgePoint, final GeoPoint bottomEdgePoint) {
-      this.point = point;
-      this.cutoffPlanes = new Membership[]{new SidedPlane(cutoffPlane1), new SidedPlane(cutoffPlane2)};
-      this.notablePoints = new GeoPoint[]{topEdgePoint, bottomEdgePoint};
-      // To construct the plane, we now just need D, which is simply the negative of the evaluation of the circle normal vector at one of the points.
-      this.circlePlane = SidedPlane.constructNormalizedPerpendicularSidedPlane(point, cutoffPlane1, topEdgePoint, bottomEdgePoint);
-    }
-    
-    /** Constructor for case (3).
-     * Generate an endpoint for an intersection, given four points.
-     *@param point is the center.
-     *@param prevCutoffPlane is the previous adjoining segment cutoff plane.
-     *@param nextCutoffPlane is the next path segment cutoff plane.
-     *@param notCand2Point is a point NOT on candidate2.
-     *@param notCand1Point is a point NOT on candidate1.
-     *@param notCand3Point is a point NOT on candidate3.
-     *@param notCand4Point is a point NOT on candidate4.
-     *@param candidate1 one of four candidate circle planes.
-     *@param candidate2 one of four candidate circle planes.
-     *@param candidate3 one of four candidate circle planes.
-     *@param candidate4 one of four candidate circle planes.
-     */
-    public SegmentEndpoint(final GeoPoint point,
-      final SidedPlane prevCutoffPlane, final SidedPlane nextCutoffPlane,
-      final GeoPoint notCand2Point, final GeoPoint notCand1Point,
-      final GeoPoint notCand3Point, final GeoPoint notCand4Point,
-      final SidedPlane candidate1, final SidedPlane candidate2, final SidedPlane candidate3, final SidedPlane candidate4) {
-      // Note: What we really need is a single plane that goes through all four points.
-      // Since that's not possible in the ellipsoid case (because three points determine a plane, not four), we
-      // need an approximation that at least creates a boundary that has no interruptions.
-      // There are three obvious choices for the third point: either (a) one of the two remaining points, or (b) the top or bottom edge
-      // intersection point.  (a) has no guarantee of continuity, while (b) is capable of producing something very far from a circle if
-      // the angle between segments is acute.
-      // The solution is to look for the side (top or bottom) that has an intersection within the shape.  We use the two points from
-      // the opposite side to determine the plane, AND we pick the third to be either of the two points on the intersecting side
-      // PROVIDED that the other point is within the final circle we come up with.
-      this.point = point;
-      
-      // We construct four separate planes, and evaluate which one includes all interior points with least overlap
-      // (Constructed beforehand because we need them for degeneracy check)
-
-      final boolean cand1IsOtherWithin = candidate1!=null?candidate1.isWithin(notCand1Point):false;
-      final boolean cand2IsOtherWithin = candidate2!=null?candidate2.isWithin(notCand2Point):false;
-      final boolean cand3IsOtherWithin = candidate3!=null?candidate3.isWithin(notCand3Point):false;
-      final boolean cand4IsOtherWithin = candidate4!=null?candidate4.isWithin(notCand4Point):false;
-      
-      if (cand1IsOtherWithin && cand2IsOtherWithin && cand3IsOtherWithin && cand4IsOtherWithin) {
-        // The only way we should see both within is if all four points are coplanar.  In that case, we default to the simplest treatment.
-        this.circlePlane = candidate1;  // doesn't matter which
-        this.notablePoints = new GeoPoint[]{notCand2Point, notCand3Point, notCand1Point, notCand4Point};
-        this.cutoffPlanes = new Membership[]{new SidedPlane(prevCutoffPlane), new SidedPlane(nextCutoffPlane)};
-      } else if (cand1IsOtherWithin) {
-        // Use candidate1, and DON'T include prevCutoffPlane in the cutoff planes list
-        this.circlePlane = candidate1;
-        this.notablePoints = new GeoPoint[]{notCand2Point, notCand3Point, notCand4Point};
-        this.cutoffPlanes = new Membership[]{new SidedPlane(nextCutoffPlane)};
-      } else if (cand2IsOtherWithin) {
-        // Use candidate2
-        this.circlePlane = candidate2;
-        this.notablePoints = new GeoPoint[]{notCand3Point, notCand4Point, notCand1Point};
-        this.cutoffPlanes = new Membership[]{new SidedPlane(nextCutoffPlane)};
-      } else if (cand3IsOtherWithin) {
-        this.circlePlane = candidate3;
-        this.notablePoints = new GeoPoint[]{notCand4Point, notCand1Point, notCand2Point};
-        this.cutoffPlanes = new Membership[]{new SidedPlane(prevCutoffPlane)};
-      } else if (cand4IsOtherWithin) {
-        this.circlePlane = candidate4;
-        this.notablePoints = new GeoPoint[]{notCand1Point, notCand2Point, notCand3Point};
-        this.cutoffPlanes = new Membership[]{new SidedPlane(prevCutoffPlane)};
-      } else {
-        // dunno what happened
-        throw new RuntimeException("Couldn't come up with a plane through three points that included the fourth");
-      }
-    }
-
-    /** Check if point is within this endpoint.
-     *@param point is the point.
-     *@return true of within.
-     */
-    public boolean isWithin(final Vector point) {
-      if (circlePlane == null)
-        return false;
-      if (!circlePlane.isWithin(point))
-        return false;
-      for (final Membership m : cutoffPlanes) {
-        if (!m.isWithin(point)) {
-          return false;
-        }
-      }
-      return true;
-    }
-
-    /** Check if point is within this endpoint.
-     *@param x is the point x.
-     *@param y is the point y.
-     *@param z is the point z.
-     *@return true of within.
-     */
-    public boolean isWithin(final double x, final double y, final double z) {
-      if (circlePlane == null)
-        return false;
-      if (!circlePlane.isWithin(x, y, z))
-        return false;
-      for (final Membership m : cutoffPlanes) {
-        if (!m.isWithin(x,y,z)) {
-          return false;
-        }
-      }
-      return true;
-    }
-
-    /** Compute interior path distance.
-     *@param distanceStyle is the distance style.
-     *@param x is the point x.
-     *@param y is the point y.
-     *@param z is the point z.
-     *@return the distance metric.
-     */
-    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 distanceStyle.computeDistance(this.point, x, y, z);
-    }
-
-    /** Compute external distance.
-     *@param distanceStyle is the distance style.
-     *@param x is the point x.
-     *@param y is the point y.
-     *@param z is the point z.
-     *@return the distance metric.
-     */
-    public double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
-      return distanceStyle.computeDistance(this.point, x, y, z);
-    }
-
-    /** Determine if this endpoint intersects a specified plane.
-     *@param planetModel is the planet model.
-     *@param p is the plane.
-     *@param notablePoints are the points associated with the plane.
-     *@param bounds are any bounds which the intersection must lie within.
-     *@return true if there is a matching intersection.
-     */
-    public boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
-      //System.err.println("  looking for intersection between plane "+p+" and circle "+circlePlane+" on proper side of "+cutoffPlanes+" within "+bounds);
-      if (circlePlane == null)
-        return false;
-      return circlePlane.intersects(planetModel, p, notablePoints, this.notablePoints, bounds, this.cutoffPlanes);
-    }
-
-    /** Get the bounds for a segment endpoint.
-     *@param planetModel is the planet model.
-     *@param bounds are the bounds to be modified.
-     */
-    public void getBounds(final PlanetModel planetModel, Bounds bounds) {
-      bounds.addPoint(point);
-      if (circlePlane == null)
-        return;
-      bounds.addPlane(planetModel, circlePlane);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-      if (!(o instanceof SegmentEndpoint))
-        return false;
-      SegmentEndpoint other = (SegmentEndpoint) o;
-      return point.equals(other.point);
-    }
-
-    @Override
-    public int hashCode() {
-      return point.hashCode();
-    }
-
-    @Override
-    public String toString() {
-      return point.toString();
-    }
-  }
-
-  /**
-   * This is the pre-calculated data for a path segment.
-   */
-  public static class PathSegment {
-    /** Starting point of the segment */
-    public final GeoPoint start;
-    /** End point of the segment */
-    public final GeoPoint end;
-    /** Place to keep any complete segment distances we've calculated so far */
-    public final Map<DistanceStyle,Double> fullDistanceCache = new HashMap<DistanceStyle,Double>();
-    /** Normalized plane connecting the two points and going through world center */
-    public final Plane normalizedConnectingPlane;
-    /** Cutoff plane parallel to connecting plane representing one side of the path segment */
-    public final SidedPlane upperConnectingPlane;
-    /** Cutoff plane parallel to connecting plane representing the other side of the path segment */
-    public final SidedPlane lowerConnectingPlane;
-    /** Plane going through the center and start point, marking the start edge of the segment */
-    public final SidedPlane startCutoffPlane;
-    /** Plane going through the center and end point, marking the end edge of the segment */
-    public final SidedPlane endCutoffPlane;
-    /** Upper right hand corner of segment */
-    public final GeoPoint URHC;
-    /** Lower right hand corner of segment */
-    public final GeoPoint LRHC;
-    /** Upper left hand corner of segment */
-    public final GeoPoint ULHC;
-    /** Lower left hand corner of segment */
-    public final GeoPoint LLHC;
-    /** Notable points for the upper connecting plane */
-    public final GeoPoint[] upperConnectingPlanePoints;
-    /** Notable points for the lower connecting plane */
-    public final GeoPoint[] lowerConnectingPlanePoints;
-    /** Notable points for the start cutoff plane */
-    public final GeoPoint[] startCutoffPlanePoints;
-    /** Notable points for the end cutoff plane */
-    public final GeoPoint[] endCutoffPlanePoints;
-
-    /** Construct a path segment.
-     *@param planetModel is the planet model.
-     *@param start is the starting point.
-     *@param end is the ending point.
-     *@param normalizedConnectingPlane is the connecting plane.
-     *@param planeBoundingOffset is the linear offset from the connecting plane to either side.
-     */
-    public PathSegment(final PlanetModel planetModel, final GeoPoint start, final GeoPoint end,
-      final Plane normalizedConnectingPlane, final double planeBoundingOffset) {
-      this.start = start;
-      this.end = end;
-      this.normalizedConnectingPlane = normalizedConnectingPlane;
-        
-      // Either start or end should be on the correct side
-      upperConnectingPlane = new SidedPlane(start, normalizedConnectingPlane, -planeBoundingOffset);
-      lowerConnectingPlane = new SidedPlane(start, normalizedConnectingPlane, planeBoundingOffset);
-      // Cutoff planes use opposite endpoints as correct side examples
-      startCutoffPlane = new SidedPlane(end, normalizedConnectingPlane, start);
-      endCutoffPlane = new SidedPlane(start, normalizedConnectingPlane, end);
-      final Membership[] upperSide = new Membership[]{upperConnectingPlane};
-      final Membership[] lowerSide = new Membership[]{lowerConnectingPlane};
-      final Membership[] startSide = new Membership[]{startCutoffPlane};
-      final Membership[] endSide = new Membership[]{endCutoffPlane};
-      GeoPoint[] points;
-      points = upperConnectingPlane.findIntersections(planetModel, startCutoffPlane, lowerSide, endSide);
-      if (points.length == 0) {
-        throw new IllegalArgumentException("Some segment boundary points are off the ellipsoid; path too wide");
-      }
-      this.ULHC = points[0];
-      points = upperConnectingPlane.findIntersections(planetModel, endCutoffPlane, lowerSide, startSide);
-      if (points.length == 0) {
-        throw new IllegalArgumentException("Some segment boundary points are off the ellipsoid; path too wide");
-      }
-      this.URHC = points[0];
-      points = lowerConnectingPlane.findIntersections(planetModel, startCutoffPlane, upperSide, endSide);
-      if (points.length == 0) {
-        throw new IllegalArgumentException("Some segment boundary points are off the ellipsoid; path too wide");
-      }
-      this.LLHC = points[0];
-      points = lowerConnectingPlane.findIntersections(planetModel, endCutoffPlane, upperSide, startSide);
-      if (points.length == 0) {
-        throw new IllegalArgumentException("Some segment boundary points are off the ellipsoid; path too wide");
-      }
-      this.LRHC = points[0];
-      upperConnectingPlanePoints = new GeoPoint[]{ULHC, URHC};
-      lowerConnectingPlanePoints = new GeoPoint[]{LLHC, LRHC};
-      startCutoffPlanePoints = new GeoPoint[]{ULHC, LLHC};
-      endCutoffPlanePoints = new GeoPoint[]{URHC, LRHC};
-    }
-
-    /** Compute the full distance along this path segment.
-     *@param distanceStyle is the distance style.
-     *@return the distance metric.
-     */
-    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();
-      }
-    }
-  
-    /** Check if point is within this segment.
-     *@param point is the point.
-     *@return true of within.
-     */
-    public boolean isWithin(final Vector point) {
-      return startCutoffPlane.isWithin(point) &&
-          endCutoffPlane.isWithin(point) &&
-          upperConnectingPlane.isWithin(point) &&
-          lowerConnectingPlane.isWithin(point);
-    }
-
-    /** Check if point is within this segment.
-     *@param x is the point x.
-     *@param y is the point y.
-     *@param z is the point z.
-     *@return true of within.
-     */
-    public boolean isWithin(final double x, final double y, final double z) {
-      return startCutoffPlane.isWithin(x, y, z) &&
-          endCutoffPlane.isWithin(x, y, z) &&
-          upperConnectingPlane.isWithin(x, y, z) &&
-          lowerConnectingPlane.isWithin(x, y, z);
-    }
-
-    /** Compute interior path distance.
-     *@param planetModel is the planet model.
-     *@param distanceStyle is the distance style.
-     *@param x is the point x.
-     *@param y is the point y.
-     *@param z is the point z.
-     *@return the distance metric.
-     */
-    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;
-
-      // (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 * 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);
-    }
-
-    /** Compute external distance.
-     *@param planetModel is the planet model.
-     *@param distanceStyle is the distance style.
-     *@param x is the point x.
-     *@param y is the point y.
-     *@param z is the point z.
-     *@return the distance metric.
-     */
-    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)));
-    }
-
-    /** Determine if this endpoint intersects a specified plane.
-     *@param planetModel is the planet model.
-     *@param p is the plane.
-     *@param notablePoints are the points associated with the plane.
-     *@param bounds are any bounds which the intersection must lie within.
-     *@return true if there is a matching intersection.
-     */
-    public boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
-      return upperConnectingPlane.intersects(planetModel, p, notablePoints, upperConnectingPlanePoints, bounds, lowerConnectingPlane, startCutoffPlane, endCutoffPlane) ||
-          lowerConnectingPlane.intersects(planetModel, p, notablePoints, lowerConnectingPlanePoints, bounds, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
-    }
-
-    /** Get the bounds for a segment endpoint.
-     *@param planetModel is the planet model.
-     *@param bounds are the bounds to be modified.
-     */
-    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).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);
-    }
-
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPoint.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPoint.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPoint.java
deleted file mode 100755
index e8a265d..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPoint.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-    
-/**
- * This class represents a point on the surface of a sphere or ellipsoid.
- *
- * @lucene.experimental
- */
-public class GeoPoint extends Vector {
-  
-  // By making lazily-evaluated variables be "volatile", we guarantee atomicity when they
-  // are updated.  This is necessary if we are using these classes in a multi-thread fashion,
-  // because we don't try to synchronize for the lazy computation.
-  
-  /** This is the lazily-evaluated magnitude.  Some constructors include it, but others don't, and
-   * we try not to create extra computation by always computing it.  Does not need to be
-   * synchronized for thread safety, because depends wholly on immutable variables of this class. */
-  protected volatile double magnitude = Double.NEGATIVE_INFINITY;
-  /** Lazily-evaluated latitude.  Does not need to be
-   * synchronized for thread safety, because depends wholly on immutable variables of this class.  */
-  protected volatile double latitude = Double.NEGATIVE_INFINITY;
-  /** Lazily-evaluated longitude.   Does not need to be
-   * synchronized for thread safety, because depends wholly on immutable variables of this class.  */
-  protected volatile double longitude = Double.NEGATIVE_INFINITY;
-
-  /** Construct a GeoPoint from the trig functions of a lat and lon pair.
-   * @param planetModel is the planetModel to put the point on.
-   * @param sinLat is the sin of the latitude.
-   * @param sinLon is the sin of the longitude.
-   * @param cosLat is the cos of the latitude.
-   * @param cosLon is the cos of the longitude.
-   * @param lat is the latitude.
-   * @param lon is the longitude.
-   */
-  public GeoPoint(final PlanetModel planetModel, final double sinLat, final double sinLon, final double cosLat, final double cosLon, final double lat, final double lon) {
-    this(computeDesiredEllipsoidMagnitude(planetModel, cosLat * cosLon, cosLat * sinLon, sinLat),
-      cosLat * cosLon, cosLat * sinLon, sinLat, lat, lon);
-  }
-  
-  /** Construct a GeoPoint from the trig functions of a lat and lon pair.
-   * @param planetModel is the planetModel to put the point on.
-   * @param sinLat is the sin of the latitude.
-   * @param sinLon is the sin of the longitude.
-   * @param cosLat is the cos of the latitude.
-   * @param cosLon is the cos of the longitude.
-   */
-  public GeoPoint(final PlanetModel planetModel, final double sinLat, final double sinLon, final double cosLat, final double cosLon) {
-    this(computeDesiredEllipsoidMagnitude(planetModel, cosLat * cosLon, cosLat * sinLon, sinLat),
-      cosLat * cosLon, cosLat * sinLon, sinLat);
-  }
-
-  /** Construct a GeoPoint from a latitude/longitude pair.
-   * @param planetModel is the planetModel to put the point on.
-   * @param lat is the latitude.
-   * @param lon is the longitude.
-   */
-  public GeoPoint(final PlanetModel planetModel, final double lat, final double lon) {
-    this(planetModel, Math.sin(lat), Math.sin(lon), Math.cos(lat), Math.cos(lon), lat, lon);
-  }
-  
-  /** Construct a GeoPoint from a unit (x,y,z) vector and a magnitude.
-   * @param magnitude is the desired magnitude, provided to put the point on the ellipsoid.
-   * @param x is the unit x value.
-   * @param y is the unit y value.
-   * @param z is the unit z value.
-   * @param lat is the latitude.
-   * @param lon is the longitude.
-   */
-  public GeoPoint(final double magnitude, final double x, final double y, final double z, double lat, double lon) {
-    super(x * magnitude, y * magnitude, z * magnitude);
-    this.magnitude = magnitude;
-    if (lat > Math.PI * 0.5 || lat < -Math.PI * 0.5) {
-      throw new IllegalArgumentException("Latitude " + lat + " is out of range: must range from -Math.PI/2 to Math.PI/2");
-    }
-    if (lon < -Math.PI || lon > Math.PI) {
-      throw new IllegalArgumentException("Longitude " + lon + " is out of range: must range from -Math.PI to Math.PI");
-    }
-    this.latitude = lat;
-    this.longitude = lon;
-  }
-
-  /** Construct a GeoPoint from a unit (x,y,z) vector and a magnitude.
-   * @param magnitude is the desired magnitude, provided to put the point on the ellipsoid.
-   * @param x is the unit x value.
-   * @param y is the unit y value.
-   * @param z is the unit z value.
-   */
-  public GeoPoint(final double magnitude, final double x, final double y, final double z) {
-    super(x * magnitude, y * magnitude, z * magnitude);
-    this.magnitude = magnitude;
-  }
-  
-  /** Construct a GeoPoint from an (x,y,z) value.
-   * The (x,y,z) tuple must be on the desired ellipsoid.
-   * @param x is the ellipsoid point x value.
-   * @param y is the ellipsoid point y value.
-   * @param z is the ellipsoid point z value.
-   */
-  public GeoPoint(final double x, final double y, final double z) {
-    super(x, y, z);
-  }
-
-  /** Compute an arc distance between two points.
-   * Note: this is an angular distance, and not a surface distance, and is therefore independent of planet model.
-   * For surface distance, see {@link org.apache.lucene.geo3d.PlanetModel#surfaceDistance(GeoPoint, GeoPoint)}
-   * @param v is the second point.
-   * @return the angle, in radians, between the two points.
-   */
-  public double arcDistance(final GeoPoint v) {
-    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.
-   */
-  public double getLatitude() {
-    double lat = this.latitude;//volatile-read once
-    if (lat == Double.NEGATIVE_INFINITY)
-      this.latitude = lat = Math.asin(z / magnitude());
-    return lat;
-  }
-  
-  /** Compute the longitude for the point.
-   * @return the longitude value.  Uses 0.0 if there is no computable longitude.
-   */
-  public double getLongitude() {
-    double lon = this.longitude;//volatile-read once
-    if (lon == Double.NEGATIVE_INFINITY) {
-      if (Math.abs(x) < MINIMUM_RESOLUTION && Math.abs(y) < MINIMUM_RESOLUTION)
-        this.longitude = lon = 0.0;
-      else
-        this.longitude = lon = Math.atan2(y,x);
-    }
-    return lon;
-  }
-  
-  /** Compute the linear magnitude of the point.
-   * @return the magnitude.
-   */
-  @Override
-  public double magnitude() {
-    double mag = this.magnitude;//volatile-read once
-    if (mag == Double.NEGATIVE_INFINITY) {
-      this.magnitude = mag = super.magnitude();
-    }
-    return mag;
-  }
-  
-  /** Compute whether point matches another.
-   *@param x is the x value
-   *@param y is the y value
-   *@param z is the z value
-   *@return true if the same.
-   */
-  public boolean isIdentical(final double x, final double y, final double z) {
-    return Math.abs(this.x - x) < MINIMUM_RESOLUTION &&
-      Math.abs(this.y - y) < MINIMUM_RESOLUTION &&
-      Math.abs(this.z - z) < MINIMUM_RESOLUTION;
-  }
-  
-  @Override
-  public String toString() {
-    if (this.longitude == Double.NEGATIVE_INFINITY) {
-      return super.toString();
-    }
-    return "[lat="+getLatitude()+", lon="+getLongitude()+"]";
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPolygon.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPolygon.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPolygon.java
deleted file mode 100644
index 634406d..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPolygon.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * GeoPolygon interface description.
- *
- * @lucene.experimental
- */
-public interface GeoPolygon extends GeoMembershipShape {
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPolygonFactory.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPolygonFactory.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPolygonFactory.java
deleted file mode 100755
index 0dc70a5..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPolygonFactory.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.List;
-
-/**
- * Class which constructs a GeoMembershipShape representing an arbitrary polygon.
- *
- * @lucene.experimental
- */
-public class GeoPolygonFactory {
-  private GeoPolygonFactory() {
-  }
-
-  /**
-   * Create a GeoMembershipShape of the right kind given the specified bounds.
-   *
-   * @param pointList        is a list of the GeoPoints to build an arbitrary polygon out of.
-   * @param convexPointIndex is the index of a single convex point whose conformation with
-   *                         its neighbors determines inside/outside for the entire polygon.
-   * @return a GeoPolygon corresponding to what was specified.
-   */
-  public static GeoPolygon makeGeoPolygon(final PlanetModel planetModel, final List<GeoPoint> pointList, final int convexPointIndex) {
-    // The basic operation uses a set of points, two points determining one particular edge, and a sided plane
-    // describing membership.
-    return buildPolygonShape(planetModel, pointList, convexPointIndex, getLegalIndex(convexPointIndex + 1, pointList.size()),
-        new SidedPlane(pointList.get(getLegalIndex(convexPointIndex - 1, pointList.size())),
-            pointList.get(convexPointIndex), pointList.get(getLegalIndex(convexPointIndex + 1, pointList.size()))),
-        false);
-  }
-
-  /** Build a GeoMembershipShape given points, starting edge, and whether starting edge is internal or not.
-   * @param pointsList        is a list of the GeoPoints to build an arbitrary polygon out of.
-   * @param startPointIndex is one of the points constituting the starting edge.
-   * @param endPointIndex is another of the points constituting the starting edge.
-   * @param startingEdge is the plane describing the starting edge.
-   * @param isInternalEdge is true if the specified edge is an internal one.
-   * @return a GeoMembershipShape corresponding to what was specified.
-   */
-  public static GeoPolygon buildPolygonShape(final PlanetModel planetModel, final List<GeoPoint> pointsList, final int startPointIndex, final int endPointIndex, final SidedPlane startingEdge, final boolean isInternalEdge) {
-    // Algorithm as follows:
-    // Start with sided edge.  Go through all points in some order.  For each new point, determine if the point is within all edges considered so far.
-    // If not, put it into a list of points for recursion.  If it is within, add new edge and keep going.
-    // Once we detect a point that is within, if there are points put aside for recursion, then call recursively.
-
-    // Current composite.  This is what we'll actually be returning.
-    final GeoCompositePolygon rval = new GeoCompositePolygon();
-
-    final List<GeoPoint> recursionList = new ArrayList<GeoPoint>();
-    final List<GeoPoint> currentList = new ArrayList<GeoPoint>();
-    final BitSet internalEdgeList = new BitSet();
-    final List<SidedPlane> currentPlanes = new ArrayList<SidedPlane>();
-
-    // Initialize the current list and current planes
-    currentList.add(pointsList.get(startPointIndex));
-    currentList.add(pointsList.get(endPointIndex));
-    internalEdgeList.set(currentPlanes.size(), isInternalEdge);
-    currentPlanes.add(startingEdge);
-
-    // Now, scan all remaining points, in order.  We'll use an index and just add to it.
-    for (int i = 0; i < pointsList.size() - 2; i++) {
-      GeoPoint newPoint = pointsList.get(getLegalIndex(i + endPointIndex + 1, pointsList.size()));
-      if (isWithin(newPoint, currentPlanes)) {
-        // Construct a sided plane based on the last two points, and the previous point
-        SidedPlane newBoundary = new SidedPlane(currentList.get(currentList.size() - 2), newPoint, currentList.get(currentList.size() - 1));
-        // Construct a sided plane based on the return trip
-        SidedPlane returnBoundary = new SidedPlane(currentList.get(currentList.size() - 1), currentList.get(0), newPoint);
-        // Verify that none of the points beyond the new point in the list are inside the polygon we'd
-        // be creating if we stopped making the current polygon right now.
-        boolean pointInside = false;
-        for (int j = i + 1; j < pointsList.size() - 2; j++) {
-          GeoPoint checkPoint = pointsList.get(getLegalIndex(j + endPointIndex + 1, pointsList.size()));
-          boolean isInside = true;
-          if (isInside && !newBoundary.isWithin(checkPoint))
-            isInside = false;
-          if (isInside && !returnBoundary.isWithin(checkPoint))
-            isInside = false;
-          if (isInside) {
-            for (SidedPlane plane : currentPlanes) {
-              if (!plane.isWithin(checkPoint)) {
-                isInside = false;
-                break;
-              }
-            }
-          }
-          if (isInside) {
-            pointInside = true;
-            break;
-          }
-        }
-        if (!pointInside) {
-          // Any excluded points?
-          boolean isInternalBoundary = recursionList.size() > 0;
-          if (isInternalBoundary) {
-            // Handle exclusion
-            recursionList.add(newPoint);
-            recursionList.add(currentList.get(currentList.size() - 1));
-            if (recursionList.size() == pointsList.size()) {
-              // We are trying to recurse with a list the same size as the one we started with.
-              // Clearly, the polygon cannot be constructed
-              throw new IllegalArgumentException("Polygon is illegal; cannot be decomposed into convex parts");
-            }
-            // We want the other side for the recursion
-            SidedPlane otherSideNewBoundary = new SidedPlane(newBoundary);
-            rval.addShape(buildPolygonShape(planetModel, recursionList, recursionList.size() - 2, recursionList.size() - 1, otherSideNewBoundary, true));
-            recursionList.clear();
-          }
-          currentList.add(newPoint);
-          internalEdgeList.set(currentPlanes.size(), isInternalBoundary);
-          currentPlanes.add(newBoundary);
-        } else {
-          recursionList.add(newPoint);
-        }
-      } else {
-        recursionList.add(newPoint);
-      }
-    }
-
-    boolean returnEdgeInternalBoundary = recursionList.size() > 0;
-    if (returnEdgeInternalBoundary) {
-      // The last step back to the start point had a recursion, so take care of that before we complete our work
-      recursionList.add(currentList.get(0));
-      recursionList.add(currentList.get(currentList.size() - 1));
-      if (recursionList.size() == pointsList.size()) {
-        // We are trying to recurse with a list the same size as the one we started with.
-        // Clearly, the polygon cannot be constructed
-        throw new IllegalArgumentException("Polygon is illegal; cannot be decomposed into convex parts");
-      }
-      // Construct a sided plane based on these two points, and the previous point
-      SidedPlane newBoundary = new SidedPlane(currentList.get(currentList.size() - 2), currentList.get(0), currentList.get(currentList.size() - 1));
-      // We want the other side for the recursion
-      SidedPlane otherSideNewBoundary = new SidedPlane(newBoundary);
-      rval.addShape(buildPolygonShape(planetModel, recursionList, recursionList.size() - 2, recursionList.size() - 1, otherSideNewBoundary, true));
-      recursionList.clear();
-    }
-    // Now, add in the current shape.
-    rval.addShape(new GeoConvexPolygon(planetModel, currentList, internalEdgeList, returnEdgeInternalBoundary));
-    //System.out.println("Done creating polygon");
-    return rval;
-  }
-
-  /** Check if a point is within a described list of planes.
-   *@param newPoint is the point. 
-   *@param currentPlanes is the list of planes.
-   *@return true if within.
-   */
-  protected static boolean isWithin(final GeoPoint newPoint, final List<SidedPlane> currentPlanes) {
-    for (SidedPlane p : currentPlanes) {
-      if (!p.isWithin(newPoint))
-        return false;
-    }
-    return true;
-  }
-
-  /** Convert raw point index into valid array position.
-   *@param index is the array index.
-   *@param size is the array size.
-   *@return an updated index.
-   */
-  protected static int getLegalIndex(int index, int size) {
-    while (index < 0) {
-      index += size;
-    }
-    while (index >= size) {
-      index -= size;
-    }
-    return index;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoRectangle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoRectangle.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoRectangle.java
deleted file mode 100755
index fc2a531..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoRectangle.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Bounding box limited on four sides (top lat, bottom lat, left lon, right lon).
- * The left-right maximum extent for this shape is PI; for anything larger, use
- * GeoWideRectangle.
- *
- * @lucene.internal
- */
-public class GeoRectangle extends GeoBaseBBox {
-  /** The top latitude of the rect */
-  protected final double topLat;
-  /** The bottom latitude of the rect */
-  protected final double bottomLat;
-  /** The left longitude of the rect */
-  protected final double leftLon;
-  /** The right longitude of the rect */
-  protected final double rightLon;
-  /** The cosine of a middle latitude */
-  protected final double cosMiddleLat;
-
-  /** The upper left hand corner point */
-  protected final GeoPoint ULHC;
-  /** The upper right hand corner point */
-  protected final GeoPoint URHC;
-  /** The lower right hand corner point */
-  protected final GeoPoint LRHC;
-  /** The lower left hand corner point */
-  protected final GeoPoint LLHC;
-
-  /** The top plane */
-  protected final SidedPlane topPlane;
-  /** The bottom plane */
-  protected final SidedPlane bottomPlane;
-  /** The left plane */
-  protected final SidedPlane leftPlane;
-  /** The right plane */
-  protected final SidedPlane rightPlane;
-
-  /** Notable points for the top plane */
-  protected final GeoPoint[] topPlanePoints;
-  /** Notable points for the bottom plane */
-  protected final GeoPoint[] bottomPlanePoints;
-  /** Notable points for the left plane */
-  protected final GeoPoint[] leftPlanePoints;
-  /** Notable points for the right plane */
-  protected final GeoPoint[] rightPlanePoints;
-
-  /** Center point */
-  protected final GeoPoint centerPoint;
-
-  /** Edge point for this rectangle */
-  protected final GeoPoint[] edgePoints;
-
-  /**
-   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
-   *@param planetModel is the planet model.
-   *@param topLat is the top latitude.
-   *@param bottomLat is the bottom latitude.
-   *@param leftLon is the left longitude.
-   *@param rightLon is the right longitude.
-   */
-  public GeoRectangle(final PlanetModel planetModel, final double topLat, final double bottomLat, final double leftLon, double rightLon) {
-    super(planetModel);
-    // Argument checking
-    if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
-      throw new IllegalArgumentException("Top latitude out of range");
-    if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
-      throw new IllegalArgumentException("Bottom latitude out of range");
-    if (topLat < bottomLat)
-      throw new IllegalArgumentException("Top latitude less than bottom latitude");
-    if (leftLon < -Math.PI || leftLon > Math.PI)
-      throw new IllegalArgumentException("Left longitude out of range");
-    if (rightLon < -Math.PI || rightLon > Math.PI)
-      throw new IllegalArgumentException("Right longitude out of range");
-    double extent = rightLon - leftLon;
-    if (extent < 0.0) {
-      extent += 2.0 * Math.PI;
-    }
-    if (extent > Math.PI)
-      throw new IllegalArgumentException("Width of rectangle too great");
-
-    this.topLat = topLat;
-    this.bottomLat = bottomLat;
-    this.leftLon = leftLon;
-    this.rightLon = rightLon;
-
-    final double sinTopLat = Math.sin(topLat);
-    final double cosTopLat = Math.cos(topLat);
-    final double sinBottomLat = Math.sin(bottomLat);
-    final double cosBottomLat = Math.cos(bottomLat);
-    final double sinLeftLon = Math.sin(leftLon);
-    final double cosLeftLon = Math.cos(leftLon);
-    final double sinRightLon = Math.sin(rightLon);
-    final double cosRightLon = Math.cos(rightLon);
-
-    // Now build the four points
-    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);
-    this.cosMiddleLat = Math.cos(middleLat);
-    // Normalize
-    while (leftLon > rightLon) {
-      rightLon += Math.PI * 2.0;
-    }
-    final double middleLon = (leftLon + rightLon) * 0.5;
-    final double sinMiddleLon = Math.sin(middleLon);
-    final double cosMiddleLon = Math.cos(middleLon);
-
-    this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
-
-    this.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
-    this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
-    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
-    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
-
-    this.topPlanePoints = new GeoPoint[]{ULHC, URHC};
-    this.bottomPlanePoints = new GeoPoint[]{LLHC, LRHC};
-    this.leftPlanePoints = new GeoPoint[]{ULHC, LLHC};
-    this.rightPlanePoints = new GeoPoint[]{URHC, LRHC};
-
-    this.edgePoints = new GeoPoint[]{ULHC};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    final double newTopLat = topLat + angle;
-    final double newBottomLat = bottomLat - angle;
-    // Figuring out when we escalate to a special case requires some prefiguring
-    double currentLonSpan = rightLon - leftLon;
-    if (currentLonSpan < 0.0)
-      currentLonSpan += Math.PI * 2.0;
-    double newLeftLon = leftLon - angle;
-    double newRightLon = rightLon + angle;
-    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
-      newLeftLon = -Math.PI;
-      newRightLon = Math.PI;
-    }
-    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return topPlane.isWithin(x, y, z) &&
-        bottomPlane.isWithin(x, y, z) &&
-        leftPlane.isWithin(x, y, z) &&
-        rightPlane.isWithin(x, y, z);
-  }
-
-  @Override
-  public double getRadius() {
-    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
-    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
-    // the distance to the right or left edge from the center.
-    final double centerAngle = (rightLon - (rightLon + leftLon) * 0.5) * cosMiddleLat;
-    final double topAngle = centerPoint.arcDistance(URHC);
-    final double bottomAngle = centerPoint.arcDistance(LLHC);
-    return Math.max(centerAngle, Math.max(topAngle, bottomAngle));
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    return centerPoint;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, bottomPlane, leftPlane, rightPlane) ||
-        p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, topPlane, leftPlane, rightPlane) ||
-        p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, topPlane, bottomPlane) ||
-        p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, topPlane, bottomPlane);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(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
-  public int getRelationship(final GeoShape path) {
-    //System.err.println(this+" getrelationship with "+path);
-    final int insideRectangle = isShapeInsideBBox(path);
-    if (insideRectangle == SOME_INSIDE) {
-      //System.err.println(" some inside");
-      return OVERLAPS;
-    }
-
-    final boolean insideShape = path.isWithin(ULHC);
-
-    if (insideRectangle == ALL_INSIDE && insideShape) {
-      //System.err.println(" inside of each other");
-      return OVERLAPS;
-    }
-
-    if (path.intersects(topPlane, topPlanePoints, bottomPlane, leftPlane, rightPlane) ||
-        path.intersects(bottomPlane, bottomPlanePoints, topPlane, leftPlane, rightPlane) ||
-        path.intersects(leftPlane, leftPlanePoints, topPlane, bottomPlane, rightPlane) ||
-        path.intersects(rightPlane, rightPlanePoints, leftPlane, topPlane, bottomPlane)) {
-      //System.err.println(" edges intersect");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE) {
-      //System.err.println(" shape inside rectangle");
-      return WITHIN;
-    }
-
-    if (insideShape) {
-      //System.err.println(" shape contains rectangle");
-      return CONTAINS;
-    }
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @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, leftPlane, rightPlane);
-    final double bottomDistance = distanceStyle.computeDistance(planetModel, bottomPlane, x,y,z, topPlane, leftPlane, rightPlane);
-    final double leftDistance = distanceStyle.computeDistance(planetModel, leftPlane, x,y,z, rightPlane, topPlane, bottomPlane);
-    final double rightDistance = distanceStyle.computeDistance(planetModel, rightPlane, x,y,z, leftPlane, topPlane, bottomPlane);
-    
-    final double ULHCDistance = distanceStyle.computeDistance(ULHC, x,y,z);
-    final double URHCDistance = distanceStyle.computeDistance(URHC, x,y,z);
-    final double LRHCDistance = distanceStyle.computeDistance(LRHC, x,y,z);
-    final double LLHCDistance = distanceStyle.computeDistance(LLHC, x,y,z);
-    
-    return Math.min(
-      Math.min(
-        Math.min(topDistance, bottomDistance),
-        Math.min(leftDistance, rightDistance)),
-      Math.min(
-        Math.min(ULHCDistance, URHCDistance),
-        Math.min(LRHCDistance, LLHCDistance)));
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof GeoRectangle))
-      return false;
-    GeoRectangle other = (GeoRectangle) o;
-    return super.equals(other) && other.ULHC.equals(ULHC) && other.LRHC.equals(LRHC);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result  + ULHC.hashCode();
-    result = 31 * result  + LRHC.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoRectangle: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
-  }
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoShape.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoShape.java
deleted file mode 100755
index 21cdba3..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoShape.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Generic shape.  This describes methods that help GeoAreas figure out
- * how they interact with a shape, for the purposes of coming up with a
- * set of geo hash values.
- *
- * @lucene.experimental
- */
-public interface GeoShape extends Membership {
-
-  /**
-   * Return a sample point that is on the outside edge/boundary of the shape.
-   *
-   * @return samples of all edge points from distinct edge sections.  Typically one point
-   * is returned, but zero or two are also possible.
-   */
-  public GeoPoint[] getEdgePoints();
-
-  /**
-   * Assess whether a plane, within the provided bounds, intersects
-   * with the shape.  Note well that this method is allowed to return "true"
-   * if there are internal edges of a composite shape which intersect the plane.
-   * Doing this can cause getRelationship() for most GeoBBox shapes to return
-   * OVERLAPS rather than the more correct CONTAINS, but that cannot be
-   * helped for some complex shapes that are built out of overlapping parts.
-   *
-   * @param plane         is the plane to assess for intersection with the shape's edges or
-   *                      bounding curves.
-   * @param notablePoints represents the intersections of the plane with the supplied
-   *                      bounds.  These are used to disambiguate when two planes are identical and it needs
-   *                      to be determined whether any points exist that fulfill all the bounds.
-   * @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.
-   */
-  public boolean intersects(final Plane plane, final GeoPoint[] notablePoints, final Membership... bounds);
-
-  /**
-   * Compute bounds for the shape.
-   *
-   * @param bounds is the input bounds object.
-   *             The input object will be modified.
-   */
-  public void getBounds(final Bounds bounds);
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSizeable.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSizeable.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSizeable.java
deleted file mode 100755
index e8c0ebb..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSizeable.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Some shapes can compute radii of a geocircle in which they are inscribed.
- *
- * @lucene.experimental
- */
-public interface GeoSizeable {
-  /**
-   * Returns the radius of a circle into which the GeoSizeable area can
-   * be inscribed.
-   *
-   * @return the radius.
-   */
-  public double getRadius();
-
-  /**
-   * Returns the center of a circle into which the area will be inscribed.
-   *
-   * @return the center.
-   */
-  public GeoPoint getCenter();
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthLatitudeZone.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthLatitudeZone.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthLatitudeZone.java
deleted file mode 100644
index 439dc1b..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthLatitudeZone.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * This GeoBBox represents an area rectangle limited only in north latitude.
- *
- * @lucene.internal
- */
-public class GeoSouthLatitudeZone extends GeoBaseBBox {
-  /** The top latitude of the zone */
-  protected final double topLat;
-  /** The cosine of the top latitude of the zone */
-  protected final double cosTopLat;
-  /** The top plane of the zone */
-  protected final SidedPlane topPlane;
-  /** An interior point of the zone */
-  protected final GeoPoint interiorPoint;
-  /** Notable points for the plane (none) */
-  protected final static GeoPoint[] planePoints = new GeoPoint[0];
-  /** A point on the top boundary */
-  protected final GeoPoint topBoundaryPoint;
-  /** Edge points; a reference to the topBoundaryPoint */
-  protected final GeoPoint[] edgePoints;
-
-  /** Constructor.
-   *@param planetModel is the planet model.
-   *@param topLat is the top latitude of the zone.
-   */
-  public GeoSouthLatitudeZone(final PlanetModel planetModel, final double topLat) {
-    super(planetModel);
-    this.topLat = topLat;
-
-    final double sinTopLat = Math.sin(topLat);
-    this.cosTopLat = Math.cos(topLat);
-
-    // Compute an interior point.  Pick one whose lat is between top and bottom.
-    final double middleLat = (topLat - Math.PI * 0.5) * 0.5;
-    final double sinMiddleLat = Math.sin(middleLat);
-    this.interiorPoint = new GeoPoint(planetModel, sinMiddleLat, 0.0, Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 1.0);
-    this.topBoundaryPoint = new GeoPoint(planetModel, sinTopLat, 0.0, Math.sqrt(1.0 - sinTopLat * sinTopLat), 1.0);
-
-    this.topPlane = new SidedPlane(interiorPoint, planetModel, sinTopLat);
-
-    this.edgePoints = new GeoPoint[]{topBoundaryPoint};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    final double newTopLat = topLat + angle;
-    final double newBottomLat = -Math.PI * 0.5;
-    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, -Math.PI, Math.PI);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return topPlane.isWithin(x, y, z);
-  }
-
-  @Override
-  public double getRadius() {
-    // This is a bit tricky.  I guess we should interpret this as meaning the angle of a circle that
-    // would contain all the bounding box points, when starting in the "center".
-    if (topLat > 0.0)
-      return Math.PI;
-    double maxCosLat = cosTopLat;
-    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;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    return p.intersects(planetModel, topPlane, notablePoints, planePoints, bounds);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    bounds
-      .addHorizontalPlane(planetModel, topLat, topPlane);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    final int insideRectangle = isShapeInsideBBox(path);
-    if (insideRectangle == SOME_INSIDE)
-      return OVERLAPS;
-
-    final boolean insideShape = path.isWithin(topBoundaryPoint);
-
-    if (insideRectangle == ALL_INSIDE && insideShape)
-      return OVERLAPS;
-
-    // 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(topPlane, planePoints))
-      return OVERLAPS;
-
-    // There is another case for latitude zones only.  This is when the boundaries of the shape all fit
-    // within the zone, but the shape includes areas outside the zone crossing a pole.
-    // In this case, the above "overlaps" check is insufficient.  We also need to check a point on either boundary
-    // whether it is within the shape.  If both such points are within, then CONTAINS is the right answer.  If
-    // one such point is within, then OVERLAPS is the right answer.
-
-    if (insideShape)
-      return CONTAINS;
-
-    if (insideRectangle == ALL_INSIDE)
-      return WITHIN;
-
-    return DISJOINT;
-  }
-
-  @Override
-  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
-    return distanceStyle.computeDistance(planetModel, topPlane, x,y,z);
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof GeoSouthLatitudeZone))
-      return false;
-    GeoSouthLatitudeZone other = (GeoSouthLatitudeZone) o;
-    return super.equals(other) && other.topBoundaryPoint.equals(topBoundaryPoint);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + topBoundaryPoint.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoSouthLatitudeZone: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + ")}";
-  }
-}
-


[35/50] [abbrv] lucene-solr git commit: LUCENE-7075: clean up LegacyNumeric* in .document javadocs

Posted by no...@apache.org.
LUCENE-7075: clean up LegacyNumeric* in .document javadocs


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

Branch: refs/heads/apiv2
Commit: 75f18ad40461d9d9a0936a12cc18fe3d8294eb89
Parents: dcb7a88
Author: Robert Muir <rm...@apache.org>
Authored: Tue Mar 8 10:54:29 2016 -0500
Committer: Robert Muir <rm...@apache.org>
Committed: Tue Mar 8 10:55:13 2016 -0500

----------------------------------------------------------------------
 .../org/apache/lucene/document/Document.java     |  6 ++----
 .../java/org/apache/lucene/document/Field.java   | 19 ++++++++++++++-----
 .../org/apache/lucene/document/TestDocument.java |  4 ++--
 3 files changed, 18 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/75f18ad4/lucene/core/src/java/org/apache/lucene/document/Document.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/Document.java b/lucene/core/src/java/org/apache/lucene/document/Document.java
index cdba083..2f44444 100644
--- a/lucene/core/src/java/org/apache/lucene/document/Document.java
+++ b/lucene/core/src/java/org/apache/lucene/document/Document.java
@@ -199,8 +199,7 @@ public final class Document implements Iterable<IndexableField> {
    * Returns an array of values of the field specified as the method parameter.
    * This method returns an empty array when there are no
    * matching fields.  It never returns null.
-   * For {@link LegacyIntField}, {@link LegacyLongField}, {@link
-   * LegacyFloatField} and {@link LegacyDoubleField} it returns the string value of the number. If you want
+   * For a numeric {@link StoredField} it returns the string value of the number. If you want
    * the actual numeric field instances back, use {@link #getFields}.
    * @param name the name of the field
    * @return a <code>String[]</code> of field values
@@ -224,8 +223,7 @@ public final class Document implements Iterable<IndexableField> {
    * this document, or null.  If multiple fields exist with this name, this
    * method returns the first value added. If only binary fields with this name
    * exist, returns null.
-   * For {@link LegacyIntField}, {@link LegacyLongField}, {@link
-   * LegacyFloatField} and {@link LegacyDoubleField} it returns the string value of the number. If you want
+   * For a numeric {@link StoredField} it returns the string value of the number. If you want
    * the actual numeric field instance back, use {@link #getField}.
    */
   public final String get(String name) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/75f18ad4/lucene/core/src/java/org/apache/lucene/document/Field.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/Field.java b/lucene/core/src/java/org/apache/lucene/document/Field.java
index dff2e58..550d1fd 100644
--- a/lucene/core/src/java/org/apache/lucene/document/Field.java
+++ b/lucene/core/src/java/org/apache/lucene/document/Field.java
@@ -33,11 +33,20 @@ import org.apache.lucene.util.BytesRef;
 
 /**
  * Expert: directly create a field for a document.  Most
- * users should use one of the sugar subclasses: {@link
- * LegacyIntField}, {@link LegacyLongField}, {@link LegacyFloatField}, {@link
- * LegacyDoubleField}, {@link BinaryDocValuesField}, {@link
- * NumericDocValuesField}, {@link SortedDocValuesField}, {@link
- * StringField}, {@link TextField}, {@link StoredField}.
+ * users should use one of the sugar subclasses: 
+ * <ul>
+ *    <li>{@link TextField}: {@link Reader} or {@link String} indexed for full-text search
+ *    <li>{@link StringField}: {@link String} indexed verbatim as a single token
+ *    <li>{@link IntPoint}: {@code int} indexed for exact/range queries.
+ *    <li>{@link LongPoint}: {@code long} indexed for exact/range queries.
+ *    <li>{@link FloatPoint}: {@code float} indexed for exact/range queries.
+ *    <li>{@link DoublePoint}: {@code double} indexed for exact/range queries.
+ *    <li>{@link SortedDocValuesField}: {@code byte[]} indexed column-wise for sorting/faceting
+ *    <li>{@link SortedSetDocValuesField}: {@code SortedSet<byte[]>} indexed column-wise for sorting/faceting
+ *    <li>{@link NumericDocValuesField}: {@code long} indexed column-wise for sorting/faceting
+ *    <li>{@link SortedNumericDocValuesField}: {@code SortedSet<long>} indexed column-wise for sorting/faceting
+ *    <li>{@link StoredField}: Stored-only value for retrieving in summary results
+ * </ul>
  *
  * <p> A field is a section of a Document. Each field has three
  * parts: name, type and value. Values may be text

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/75f18ad4/lucene/core/src/test/org/apache/lucene/document/TestDocument.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/document/TestDocument.java b/lucene/core/src/test/org/apache/lucene/document/TestDocument.java
index bd873ec..50c1ed0 100644
--- a/lucene/core/src/test/org/apache/lucene/document/TestDocument.java
+++ b/lucene/core/src/test/org/apache/lucene/document/TestDocument.java
@@ -340,10 +340,10 @@ public class TestDocument extends LuceneTestCase {
   
   public void testNumericFieldAsString() throws Exception {
     Document doc = new Document();
-    doc.add(new LegacyIntField("int", 5, Field.Store.YES));
+    doc.add(new StoredField("int", 5));
     assertEquals("5", doc.get("int"));
     assertNull(doc.get("somethingElse"));
-    doc.add(new LegacyIntField("int", 4, Field.Store.YES));
+    doc.add(new StoredField("int", 4));
     assertArrayEquals(new String[] { "5", "4" }, doc.getValues("int"));
     
     Directory dir = newDirectory();


[05/50] [abbrv] lucene-solr git commit: Merge remote-tracking branch 'origin/master'

Posted by no...@apache.org.
Merge remote-tracking branch 'origin/master'


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

Branch: refs/heads/apiv2
Commit: b87e3920976b3c7f7c765bb6d6ad1eeabd539c30
Parents: f2c281a 9617d3d
Author: Noble Paul <no...@apache.org>
Authored: Mon Mar 7 22:48:25 2016 +0530
Committer: Noble Paul <no...@apache.org>
Committed: Mon Mar 7 22:48:25 2016 +0530

----------------------------------------------------------------------
 dev-tools/scripts/smokeTestRelease.py | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------



[46/50] [abbrv] lucene-solr git commit: fix random float test to do the +/- 1 ulp in float space

Posted by no...@apache.org.
fix random float test to do the +/- 1 ulp in float space


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

Branch: refs/heads/apiv2
Commit: a6c8ccbc99a9fc83cc5ddfcfd65f9c3c4d4e920c
Parents: d776f7b
Author: Mike McCandless <mi...@apache.org>
Authored: Tue Mar 8 17:21:12 2016 -0500
Committer: Mike McCandless <mi...@apache.org>
Committed: Tue Mar 8 17:22:31 2016 -0500

----------------------------------------------------------------------
 .../lucene/facet/range/TestRangeFacetCounts.java    | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a6c8ccbc/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java
----------------------------------------------------------------------
diff --git a/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java b/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java
index 9fde6e3..9f8b109 100644
--- a/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java
+++ b/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java
@@ -532,6 +532,8 @@ public class TestRangeFacetCounts extends FacetTestCase {
       int[] expectedCounts = new int[numRange];
       float minAcceptedValue = Float.POSITIVE_INFINITY;
       float maxAcceptedValue = Float.NEGATIVE_INFINITY;
+      boolean[] rangeMinIncl = new boolean[numRange];
+      boolean[] rangeMaxIncl = new boolean[numRange];
       if (VERBOSE) {
         System.out.println("TEST: " + numRange + " ranges");
       }
@@ -582,6 +584,8 @@ public class TestRangeFacetCounts extends FacetTestCase {
           minIncl = random().nextBoolean();
           maxIncl = random().nextBoolean();
         }
+        rangeMinIncl[rangeID] = minIncl;
+        rangeMaxIncl[rangeID] = maxIncl;
         ranges[rangeID] = new DoubleRange("r" + rangeID, min, minIncl, max, maxIncl);
 
         if (VERBOSE) {
@@ -642,7 +646,17 @@ public class TestRangeFacetCounts extends FacetTestCase {
         // Test drill-down:
         DrillDownQuery ddq = new DrillDownQuery(config);
         if (random().nextBoolean()) {
-          ddq.add("field", FloatPoint.newRangeQuery("field", (float) range.min, (float) range.max));
+          // We must do the nextUp/down in float space, here, because the nextUp that DoubleRange did in double space, when cast back to float,
+          // in fact does nothing!
+          float minFloat = (float) range.min;
+          if (rangeMinIncl[rangeID] == false) {
+            minFloat = Math.nextUp(minFloat);
+          }
+          float maxFloat = (float) range.max;
+          if (rangeMaxIncl[rangeID] == false) {
+            maxFloat = Math.nextAfter(maxFloat, Float.NEGATIVE_INFINITY);
+          }
+          ddq.add("field", FloatPoint.newRangeQuery("field", minFloat, maxFloat));
         } else {
           ddq.add("field", range.getQuery(fastMatchQuery, vs));
         }


[37/50] [abbrv] lucene-solr git commit: LUCENE-6952: Make most Filter* classes abstract.

Posted by no...@apache.org.
LUCENE-6952: Make most Filter* classes abstract.


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

Branch: refs/heads/apiv2
Commit: 9393a3190ce6af48ae0aac40d5d4b17c3b5d5423
Parents: f9fbf8b
Author: David Smiley <ds...@apache.org>
Authored: Tue Mar 8 12:36:46 2016 -0500
Committer: David Smiley <ds...@apache.org>
Committed: Tue Mar 8 12:36:46 2016 -0500

----------------------------------------------------------------------
 lucene/CHANGES.txt                                        |  4 ++++
 .../java/org/apache/lucene/index/FilterCodecReader.java   |  2 +-
 .../java/org/apache/lucene/index/FilterLeafReader.java    | 10 +++++-----
 .../java/org/apache/lucene/search/FilterCollector.java    |  2 +-
 .../org/apache/lucene/search/FilterLeafCollector.java     |  2 +-
 .../src/java/org/apache/lucene/store/FilterDirectory.java |  2 +-
 .../org/apache/lucene/index/TestFilterLeafReader.java     |  2 +-
 .../test/org/apache/lucene/store/TestFilterDirectory.java |  4 ++--
 .../org/apache/lucene/index/MockRandomMergePolicy.java    |  2 +-
 .../org/apache/lucene/mockfile/FilterFileChannel.java     |  2 +-
 .../java/org/apache/lucene/mockfile/FilterFileStore.java  |  2 +-
 .../java/org/apache/lucene/mockfile/FilterFileSystem.java |  2 +-
 .../apache/lucene/mockfile/FilterFileSystemProvider.java  |  2 +-
 .../org/apache/lucene/mockfile/FilterOutputStream2.java   |  2 +-
 14 files changed, 22 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9393a319/lucene/CHANGES.txt
----------------------------------------------------------------------
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 65281b5..7e803cf 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -135,6 +135,10 @@ API Changes
 
 * LUCENE-7056: Geo3D classes are in different packages now. (David Smiley)
 
+* LUCENE-6952: These classes are now abstract: FilterCodecReader, FilterLeafReader,
+  FilterCollector, FilterDirectory.  And some Filter* classes in
+  lucene-test-framework too. (David Smiley)
+
 Optimizations
 
 * LUCENE-6891: Use prefix coding when writing points in 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9393a319/lucene/core/src/java/org/apache/lucene/index/FilterCodecReader.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/FilterCodecReader.java b/lucene/core/src/java/org/apache/lucene/index/FilterCodecReader.java
index 41f0984..c35dc67 100644
--- a/lucene/core/src/java/org/apache/lucene/index/FilterCodecReader.java
+++ b/lucene/core/src/java/org/apache/lucene/index/FilterCodecReader.java
@@ -32,7 +32,7 @@ import org.apache.lucene.util.Bits;
  * uses as its basic source of data, possibly transforming the data along the
  * way or providing additional functionality.
  */
-public class FilterCodecReader extends CodecReader {
+public abstract class FilterCodecReader extends CodecReader {
   /** 
    * The underlying CodecReader instance. 
    */

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9393a319/lucene/core/src/java/org/apache/lucene/index/FilterLeafReader.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/FilterLeafReader.java b/lucene/core/src/java/org/apache/lucene/index/FilterLeafReader.java
index 98365a6..1d593c3 100644
--- a/lucene/core/src/java/org/apache/lucene/index/FilterLeafReader.java
+++ b/lucene/core/src/java/org/apache/lucene/index/FilterLeafReader.java
@@ -44,7 +44,7 @@ import org.apache.lucene.util.BytesRef;
  * overridden as well if the {@link #getLiveDocs() live docs} are not changed
  * either.
  */
-public class FilterLeafReader extends LeafReader {
+public abstract class FilterLeafReader extends LeafReader {
 
   /** Get the wrapped instance by <code>reader</code> as long as this reader is
    *  an instance of {@link FilterLeafReader}.  */
@@ -57,7 +57,7 @@ public class FilterLeafReader extends LeafReader {
 
   /** Base class for filtering {@link Fields}
    *  implementations. */
-  public static class FilterFields extends Fields {
+  public abstract static class FilterFields extends Fields {
     /** The underlying Fields instance. */
     protected final Fields in;
 
@@ -93,7 +93,7 @@ public class FilterLeafReader extends LeafReader {
    * these terms are going to be intersected with automata, you could consider
    * overriding {@link #intersect} for better performance.
    */
-  public static class FilterTerms extends Terms {
+  public abstract static class FilterTerms extends Terms {
     /** The underlying Terms instance. */
     protected final Terms in;
 
@@ -160,7 +160,7 @@ public class FilterLeafReader extends LeafReader {
   }
 
   /** Base class for filtering {@link TermsEnum} implementations. */
-  public static class FilterTermsEnum extends TermsEnum {
+  public abstract static class FilterTermsEnum extends TermsEnum {
     /** The underlying TermsEnum instance. */
     protected final TermsEnum in;
 
@@ -223,7 +223,7 @@ public class FilterLeafReader extends LeafReader {
   }
 
   /** Base class for filtering {@link PostingsEnum} implementations. */
-  public static class FilterPostingsEnum extends PostingsEnum {
+  public abstract static class FilterPostingsEnum extends PostingsEnum {
     /** The underlying PostingsEnum instance. */
     protected final PostingsEnum in;
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9393a319/lucene/core/src/java/org/apache/lucene/search/FilterCollector.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/FilterCollector.java b/lucene/core/src/java/org/apache/lucene/search/FilterCollector.java
index d290330..d4ec914 100644
--- a/lucene/core/src/java/org/apache/lucene/search/FilterCollector.java
+++ b/lucene/core/src/java/org/apache/lucene/search/FilterCollector.java
@@ -26,7 +26,7 @@ import org.apache.lucene.index.LeafReaderContext;
  *
  * @lucene.experimental
  */
-public class FilterCollector implements Collector {
+public abstract class FilterCollector implements Collector {
 
   protected final Collector in;
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9393a319/lucene/core/src/java/org/apache/lucene/search/FilterLeafCollector.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/FilterLeafCollector.java b/lucene/core/src/java/org/apache/lucene/search/FilterLeafCollector.java
index ab15bab..b55410c 100644
--- a/lucene/core/src/java/org/apache/lucene/search/FilterLeafCollector.java
+++ b/lucene/core/src/java/org/apache/lucene/search/FilterLeafCollector.java
@@ -24,7 +24,7 @@ import java.io.IOException;
  *
  * @lucene.experimental
  */
-public class FilterLeafCollector implements LeafCollector {
+public abstract class FilterLeafCollector implements LeafCollector {
 
   protected final LeafCollector in;
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9393a319/lucene/core/src/java/org/apache/lucene/store/FilterDirectory.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/store/FilterDirectory.java b/lucene/core/src/java/org/apache/lucene/store/FilterDirectory.java
index 5df5713..8148b5a 100644
--- a/lucene/core/src/java/org/apache/lucene/store/FilterDirectory.java
+++ b/lucene/core/src/java/org/apache/lucene/store/FilterDirectory.java
@@ -29,7 +29,7 @@ import java.util.Collection;
  *  {@link Directory} or {@link BaseDirectory} rather than try to reuse
  *  functionality of existing {@link Directory}s by extending this class.
  *  @lucene.internal */
-public class FilterDirectory extends Directory {
+public abstract class FilterDirectory extends Directory {
 
   /** Get the wrapped instance by <code>dir</code> as long as this reader is
    *  an instance of {@link FilterDirectory}.  */

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9393a319/lucene/core/src/test/org/apache/lucene/index/TestFilterLeafReader.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestFilterLeafReader.java b/lucene/core/src/test/org/apache/lucene/index/TestFilterLeafReader.java
index 82fb3bc..cad47a4 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestFilterLeafReader.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestFilterLeafReader.java
@@ -196,7 +196,7 @@ public class TestFilterLeafReader extends LuceneTestCase {
     w.addDocument(new Document());
     DirectoryReader dr = w.getReader();
     LeafReader r = dr.leaves().get(0).reader();
-    FilterLeafReader r2 = new FilterLeafReader(r);
+    FilterLeafReader r2 = new FilterLeafReader(r) {};
     assertEquals(r, r2.getDelegate());
     assertEquals(r, FilterLeafReader.unwrap(r2));
     w.close();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9393a319/lucene/core/src/test/org/apache/lucene/store/TestFilterDirectory.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/store/TestFilterDirectory.java b/lucene/core/src/test/org/apache/lucene/store/TestFilterDirectory.java
index 7fe9bc2..6224140 100644
--- a/lucene/core/src/test/org/apache/lucene/store/TestFilterDirectory.java
+++ b/lucene/core/src/test/org/apache/lucene/store/TestFilterDirectory.java
@@ -29,7 +29,7 @@ public class TestFilterDirectory extends BaseDirectoryTestCase {
 
   @Override
   protected Directory getDirectory(Path path) throws IOException {
-    return new FilterDirectory(new RAMDirectory());
+    return new FilterDirectory(new RAMDirectory()) {};
   }
   
   @Test
@@ -48,7 +48,7 @@ public class TestFilterDirectory extends BaseDirectoryTestCase {
 
   public void testUnwrap() throws IOException {
     Directory dir = FSDirectory.open(createTempDir());
-    FilterDirectory dir2 = new FilterDirectory(dir);
+    FilterDirectory dir2 = new FilterDirectory(dir) {};
     assertEquals(dir, dir2.getDelegate());
     assertEquals(dir, FilterDirectory.unwrap(dir2));
     dir2.close();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9393a319/lucene/test-framework/src/java/org/apache/lucene/index/MockRandomMergePolicy.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/index/MockRandomMergePolicy.java b/lucene/test-framework/src/java/org/apache/lucene/index/MockRandomMergePolicy.java
index bcee1b6..b40ac26 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/index/MockRandomMergePolicy.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/index/MockRandomMergePolicy.java
@@ -159,7 +159,7 @@ public class MockRandomMergePolicy extends MergePolicy {
             if (LuceneTestCase.VERBOSE) {
               System.out.println("NOTE: MockRandomMergePolicy now swaps in a SlowCodecReaderWrapper for merging reader=" + readers.get(i));
             }
-            readers.set(i, SlowCodecReaderWrapper.wrap(new FilterLeafReader(readers.get(i))));
+            readers.set(i, SlowCodecReaderWrapper.wrap(new FilterLeafReader(readers.get(i)) {}));
           } else if (thingToDo == 1) {
             // renumber fields
             // NOTE: currently this only "blocks" bulk merges just by

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9393a319/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileChannel.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileChannel.java b/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileChannel.java
index 0c95af0..ccc6e7a 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileChannel.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileChannel.java
@@ -31,7 +31,7 @@ import java.util.Objects;
  * source of data, possibly transforming the data along the 
  * way or providing additional functionality. 
  */
-public class FilterFileChannel extends FileChannel {
+public abstract class FilterFileChannel extends FileChannel {
   
   /** 
    * The underlying {@code FileChannel} instance. 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9393a319/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileStore.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileStore.java b/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileStore.java
index dc90799..423b32d 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileStore.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileStore.java
@@ -28,7 +28,7 @@ import java.util.Objects;
  * source of data, possibly transforming the data along the 
  * way or providing additional functionality. 
  */
-public class FilterFileStore extends FileStore {
+public abstract class FilterFileStore extends FileStore {
   
   /** 
    * The underlying {@code FileStore} instance. 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9393a319/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileSystem.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileSystem.java b/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileSystem.java
index d79ed35..e24506d 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileSystem.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileSystem.java
@@ -131,7 +131,7 @@ public class FilterFileSystem extends FileSystem {
 
         @Override
         public FileStore next() {
-          return new FilterFileStore(iterator.next(), parent.getScheme());
+          return new FilterFileStore(iterator.next(), parent.getScheme()) {};
         }
         
         @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9393a319/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileSystemProvider.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileSystemProvider.java b/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileSystemProvider.java
index c9c0165..8a7ff75 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileSystemProvider.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterFileSystemProvider.java
@@ -48,7 +48,7 @@ import java.util.concurrent.ExecutorService;
  * source of data, possibly transforming the data along the 
  * way or providing additional functionality. 
  */
-public class FilterFileSystemProvider extends FileSystemProvider {
+public abstract class FilterFileSystemProvider extends FileSystemProvider {
   
   /** 
    * The underlying {@code FileSystemProvider}. 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9393a319/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterOutputStream2.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterOutputStream2.java b/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterOutputStream2.java
index dbf7a95..5413c87 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterOutputStream2.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/mockfile/FilterOutputStream2.java
@@ -34,7 +34,7 @@ import java.util.Objects;
  * that just overrides {@code close} will not force bytes to be 
  * written one-at-a-time.
  */
-public class FilterOutputStream2 extends OutputStream {
+public abstract class FilterOutputStream2 extends OutputStream {
   
   /** 
    * The underlying {@code OutputStream} instance. 


[20/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthRectangle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthRectangle.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthRectangle.java
deleted file mode 100644
index eb6526b..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthRectangle.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Bounding box limited on three sides (top lat, left lon, right lon).  The
- * other corner is the south pole.
- * The left-right maximum extent for this shape is PI; for anything larger, use
- * {@link GeoWideSouthRectangle}.
- *
- * @lucene.internal
- */
-public class GeoSouthRectangle extends GeoBaseBBox {
-  /** The top latitude of the rect */
-  protected final double topLat;
-  /** The left longitude of the rect */
-  protected final double leftLon;
-  /** The right longitude of the rect */
-  protected final double rightLon;
-  /** The cosine of a middle latitude */
-  protected final double cosMiddleLat;
-  /** The upper left hand corner of the rectangle */
-  protected final GeoPoint ULHC;
-  /** The upper right hand corner of the rectangle */
-  protected final GeoPoint URHC;
-
-  /** The top plane */
-  protected final SidedPlane topPlane;
-  /** The left plane */
-  protected final SidedPlane leftPlane;
-  /** The right plane */
-  protected final SidedPlane rightPlane;
-
-  /** Notable points for the top plane */
-  protected final GeoPoint[] topPlanePoints;
-  /** Notable points for the left plane */
-  protected final GeoPoint[] leftPlanePoints;
-  /** Notable points for the right plane */
-  protected final GeoPoint[] rightPlanePoints;
-
-  /** The center point */
-  protected final GeoPoint centerPoint;
-
-  /** A point on the edge */
-  protected final GeoPoint[] edgePoints;
-
-  /**
-   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
-   *@param planetModel is the planet model.
-   *@param topLat is the top latitude.
-   *@param leftLon is the left longitude.
-   *@param rightLon is the right longitude.
-   */
-  public GeoSouthRectangle(final PlanetModel planetModel, final double topLat, final double leftLon, double rightLon) {
-    super(planetModel);
-    // Argument checking
-    if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
-      throw new IllegalArgumentException("Top latitude out of range");
-    if (leftLon < -Math.PI || leftLon > Math.PI)
-      throw new IllegalArgumentException("Left longitude out of range");
-    if (rightLon < -Math.PI || rightLon > Math.PI)
-      throw new IllegalArgumentException("Right longitude out of range");
-    double extent = rightLon - leftLon;
-    if (extent < 0.0) {
-      extent += 2.0 * Math.PI;
-    }
-    if (extent > Math.PI)
-      throw new IllegalArgumentException("Width of rectangle too great");
-
-    this.topLat = topLat;
-    this.leftLon = leftLon;
-    this.rightLon = rightLon;
-
-    final double sinTopLat = Math.sin(topLat);
-    final double cosTopLat = Math.cos(topLat);
-    final double sinLeftLon = Math.sin(leftLon);
-    final double cosLeftLon = Math.cos(leftLon);
-    final double sinRightLon = Math.sin(rightLon);
-    final double cosRightLon = Math.cos(rightLon);
-
-    // Now build the four points
-    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);
-    this.cosMiddleLat = Math.cos(middleLat);
-    // Normalize
-    while (leftLon > rightLon) {
-      rightLon += Math.PI * 2.0;
-    }
-    final double middleLon = (leftLon + rightLon) * 0.5;
-    final double sinMiddleLon = Math.sin(middleLon);
-    final double cosMiddleLon = Math.cos(middleLon);
-
-    this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
-
-    this.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
-    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
-    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
-
-    this.topPlanePoints = new GeoPoint[]{ULHC, URHC};
-    this.leftPlanePoints = new GeoPoint[]{ULHC, planetModel.SOUTH_POLE};
-    this.rightPlanePoints = new GeoPoint[]{URHC, planetModel.SOUTH_POLE};
-    
-    this.edgePoints = new GeoPoint[]{planetModel.SOUTH_POLE};
-
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    final double newTopLat = topLat + angle;
-    final double newBottomLat = -Math.PI * 0.5;
-    // Figuring out when we escalate to a special case requires some prefiguring
-    double currentLonSpan = rightLon - leftLon;
-    if (currentLonSpan < 0.0)
-      currentLonSpan += Math.PI * 2.0;
-    double newLeftLon = leftLon - angle;
-    double newRightLon = rightLon + angle;
-    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
-      newLeftLon = -Math.PI;
-      newRightLon = Math.PI;
-    }
-    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return topPlane.isWithin(x, y, z) &&
-        leftPlane.isWithin(x, y, z) &&
-        rightPlane.isWithin(x, y, z);
-  }
-
-  @Override
-  public double getRadius() {
-    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
-    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
-    // the distance to the right or left edge from the center.
-    final double centerAngle = (rightLon - (rightLon + leftLon) * 0.5) * cosMiddleLat;
-    final double topAngle = centerPoint.arcDistance(URHC);
-    return Math.max(centerAngle, topAngle);
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    return centerPoint;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, leftPlane, rightPlane) ||
-        p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, topPlane) ||
-        p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, topPlane);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    bounds
-      .addHorizontalPlane(planetModel, topLat, topPlane, leftPlane, rightPlane)
-      .addVerticalPlane(planetModel, leftLon, leftPlane, topPlane, rightPlane)
-      .addVerticalPlane(planetModel, rightLon, rightPlane, topPlane, leftPlane)
-      .addPoint(URHC).addPoint(ULHC).addPoint(planetModel.SOUTH_POLE);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    //System.err.println(this+" getrelationship with "+path);
-    final int insideRectangle = isShapeInsideBBox(path);
-    if (insideRectangle == SOME_INSIDE) {
-      //System.err.println(" some inside");
-      return OVERLAPS;
-    }
-
-    final boolean insideShape = path.isWithin(planetModel.SOUTH_POLE);
-
-    if (insideRectangle == ALL_INSIDE && insideShape) {
-      //System.err.println(" inside of each other");
-      return OVERLAPS;
-    }
-
-    if (path.intersects(topPlane, topPlanePoints, leftPlane, rightPlane) ||
-        path.intersects(leftPlane, leftPlanePoints, topPlane, rightPlane) ||
-        path.intersects(rightPlane, rightPlanePoints, leftPlane, topPlane)) {
-      //System.err.println(" edges intersect");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE) {
-      //System.err.println(" shape inside rectangle");
-      return WITHIN;
-    }
-
-    if (insideShape) {
-      //System.err.println(" shape contains rectangle");
-      return CONTAINS;
-    }
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @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, leftPlane, rightPlane);
-    final double leftDistance = distanceStyle.computeDistance(planetModel, leftPlane, x,y,z, rightPlane, topPlane);
-    final double rightDistance = distanceStyle.computeDistance(planetModel, rightPlane, x,y,z, leftPlane, topPlane);
-    
-    final double ULHCDistance = distanceStyle.computeDistance(ULHC, x,y,z);
-    final double URHCDistance = distanceStyle.computeDistance(URHC, x,y,z);
-    
-    return Math.min(
-      Math.min(
-        topDistance,
-        Math.min(leftDistance, rightDistance)),
-      Math.min(ULHCDistance, URHCDistance));
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof GeoSouthRectangle))
-      return false;
-    GeoSouthRectangle other = (GeoSouthRectangle) o;
-    return super.equals(other) && other.ULHC.equals(ULHC) && other.URHC.equals(URHC);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + ULHC.hashCode();
-    result = 31 * result + URHC.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoSouthRectangle: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
-  }
-}
-  
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoStandardCircle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoStandardCircle.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoStandardCircle.java
deleted file mode 100755
index 0304d53..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoStandardCircle.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Circular area with a center and radius.
- *
- * @lucene.experimental
- */
-public class GeoStandardCircle extends GeoBaseCircle {
-  /** Center of circle */
-  protected final GeoPoint center;
-  /** Cutoff angle of circle (not quite the same thing as radius) */
-  protected final double cutoffAngle;
-  /** The plane describing the circle (really an ellipse on a non-spherical world) */
-  protected final SidedPlane circlePlane;
-  /** A point that is on the world and on the circle plane */
-  protected final GeoPoint[] edgePoints;
-  /** Notable points for a circle -- there aren't any */
-  protected static final GeoPoint[] circlePoints = new GeoPoint[0];
-
-  /** Constructor.
-   *@param planetModel is the planet model.
-   *@param lat is the center latitude.
-   *@param lon is the center longitude.
-   *@param cutoffAngle is the cutoff angle for the circle.
-   */
-  public GeoStandardCircle(final PlanetModel planetModel, final double lat, final double lon, final double cutoffAngle) {
-    super(planetModel);
-    if (lat < -Math.PI * 0.5 || lat > Math.PI * 0.5)
-      throw new IllegalArgumentException("Latitude out of bounds");
-    if (lon < -Math.PI || lon > Math.PI)
-      throw new IllegalArgumentException("Longitude out of bounds");
-    if (cutoffAngle < 0.0 || cutoffAngle > Math.PI)
-      throw new IllegalArgumentException("Cutoff angle out of bounds");
-    if (cutoffAngle < Vector.MINIMUM_RESOLUTION)
-      throw new IllegalArgumentException("Cutoff angle cannot be effectively zero");
-    this.center = new GeoPoint(planetModel, lat, lon);
-    // In an ellipsoidal world, cutoff distances make no sense, unfortunately.  Only membership
-    // can be used to make in/out determination.
-    this.cutoffAngle = cutoffAngle;
-    // Compute two points on the circle, with the right angle from the center.  We'll use these
-    // to obtain the perpendicular plane to the circle.
-    double upperLat = lat + cutoffAngle;
-    double upperLon = lon;
-    if (upperLat > Math.PI * 0.5) {
-      upperLon += Math.PI;
-      if (upperLon > Math.PI)
-        upperLon -= 2.0 * Math.PI;
-      upperLat = Math.PI - upperLat;
-    }
-    double lowerLat = lat - cutoffAngle;
-    double lowerLon = lon;
-    if (lowerLat < -Math.PI * 0.5) {
-      lowerLon += Math.PI;
-      if (lowerLon > Math.PI)
-        lowerLon -= 2.0 * Math.PI;
-      lowerLat = -Math.PI - lowerLat;
-    }
-    final GeoPoint upperPoint = new GeoPoint(planetModel, upperLat, upperLon);
-    final GeoPoint lowerPoint = new GeoPoint(planetModel, lowerLat, lowerLon);
-    if (Math.abs(cutoffAngle - Math.PI) < Vector.MINIMUM_RESOLUTION) {
-      // Circle is the whole world
-      this.circlePlane = null;
-      this.edgePoints = new GeoPoint[0];
-    } else {
-      // Construct normal plane
-      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)
-        throw new IllegalArgumentException("Couldn't construct circle plane, probably too small?  Cutoff angle = "+cutoffAngle+"; upperPoint = "+upperPoint+"; lowerPoint = "+lowerPoint);
-      final GeoPoint recomputedIntersectionPoint = circlePlane.getSampleIntersectionPoint(planetModel, normalPlane);
-      if (recomputedIntersectionPoint == null)
-        throw new IllegalArgumentException("Couldn't construct intersection point, probably circle too small?  Plane = "+circlePlane);
-      this.edgePoints = new GeoPoint[]{recomputedIntersectionPoint};
-    }
-  }
-
-  @Override
-  public double getRadius() {
-    return cutoffAngle;
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    return center;
-  }
-
-  @Override
-  protected double distance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
-    return distanceStyle.computeDistance(this.center, x, y, z);
-  }
-
-  @Override
-  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
-    return distanceStyle.computeDistance(planetModel, circlePlane, x, y, z);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    if (circlePlane == null) {
-      return true;
-    }
-    // Fastest way of determining membership
-    return circlePlane.isWithin(x, y, z);
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    if (circlePlane == null) {
-      return false;
-    }
-    return circlePlane.intersects(planetModel, p, notablePoints, circlePoints, bounds);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    if (circlePlane == null) {
-      // Entire world; should already be covered
-      return;
-    }
-    bounds.addPoint(center);
-    bounds.addPlane(planetModel, circlePlane);
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof GeoStandardCircle))
-      return false;
-    GeoStandardCircle other = (GeoStandardCircle) o;
-    return super.equals(other) && other.center.equals(center) && other.cutoffAngle == cutoffAngle;
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + center.hashCode();
-    long temp = Double.doubleToLongBits(cutoffAngle);
-    result = 31 * result + (int) (temp ^ (temp >>> 32));
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoStandardCircle: {planetmodel=" + planetModel+", center=" + center + ", radius=" + cutoffAngle + "(" + cutoffAngle * 180.0 / Math.PI + ")}";
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideDegenerateHorizontalLine.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideDegenerateHorizontalLine.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideDegenerateHorizontalLine.java
deleted file mode 100644
index a9af5b2..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideDegenerateHorizontalLine.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Degenerate bounding box wider than PI and limited on two sides (left lon, right lon).
- *
- * @lucene.internal
- */
-public class GeoWideDegenerateHorizontalLine extends GeoBaseBBox {
-  /** The latitude of the line */
-  protected final double latitude;
-  /** The left longitude cutoff of the line */
-  protected final double leftLon;
-  /** The right longitude cutoff of the line */
-  protected final double rightLon;
-
-  /** The left end of the line */
-  protected final GeoPoint LHC;
-  /** The right end of the line */
-  protected final GeoPoint RHC;
-
-  /** The plane the line is in */
-  protected final Plane plane;
-  /** The left cutoff plane */
-  protected final SidedPlane leftPlane;
-  /** The right cutoff plane */
-  protected final SidedPlane rightPlane;
-
-  /** Notable points for the line */
-  protected final GeoPoint[] planePoints;
-
-  /** Center point for the line */
-  protected final GeoPoint centerPoint;
-
-  /** Left/right combination bound */
-  protected final EitherBound eitherBound;
-
-  /** A point on the line */
-  protected final GeoPoint[] edgePoints;
-
-  /**
-   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}.
-   * Horizontal angle must be greater than or equal to PI.
-   *@param planetModel is the planet model.
-   *@param latitude is the line latitude.
-   *@param leftLon is the left cutoff longitude.
-   *@param rightLon is the right cutoff longitude.
-   */
-  public GeoWideDegenerateHorizontalLine(final PlanetModel planetModel, final double latitude, final double leftLon, double rightLon) {
-    super(planetModel);
-    // Argument checking
-    if (latitude > Math.PI * 0.5 || latitude < -Math.PI * 0.5)
-      throw new IllegalArgumentException("Latitude out of range");
-    if (leftLon < -Math.PI || leftLon > Math.PI)
-      throw new IllegalArgumentException("Left longitude out of range");
-    if (rightLon < -Math.PI || rightLon > Math.PI)
-      throw new IllegalArgumentException("Right longitude out of range");
-    double extent = rightLon - leftLon;
-    if (extent < 0.0) {
-      extent += 2.0 * Math.PI;
-    }
-    if (extent < Math.PI)
-      throw new IllegalArgumentException("Width of rectangle too small");
-
-    this.latitude = latitude;
-    this.leftLon = leftLon;
-    this.rightLon = rightLon;
-
-    final double sinLatitude = Math.sin(latitude);
-    final double cosLatitude = Math.cos(latitude);
-    final double sinLeftLon = Math.sin(leftLon);
-    final double cosLeftLon = Math.cos(leftLon);
-    final double sinRightLon = Math.sin(rightLon);
-    final double cosRightLon = Math.cos(rightLon);
-
-    // Now build the two points
-    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);
-
-    // Normalize
-    while (leftLon > rightLon) {
-      rightLon += Math.PI * 2.0;
-    }
-    double middleLon = (leftLon + rightLon) * 0.5;
-    double sinMiddleLon = Math.sin(middleLon);
-    double cosMiddleLon = Math.cos(middleLon);
-
-    this.centerPoint = new GeoPoint(planetModel, sinLatitude, sinMiddleLon, cosLatitude, cosMiddleLon);
-
-    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
-    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
-
-    this.planePoints = new GeoPoint[]{LHC, RHC};
-
-    this.eitherBound = new EitherBound();
-
-    this.edgePoints = new GeoPoint[]{centerPoint};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    final double newTopLat = latitude + angle;
-    final double newBottomLat = latitude - angle;
-    // Figuring out when we escalate to a special case requires some prefiguring
-    double currentLonSpan = rightLon - leftLon;
-    if (currentLonSpan < 0.0)
-      currentLonSpan += Math.PI * 2.0;
-    double newLeftLon = leftLon - angle;
-    double newRightLon = rightLon + angle;
-    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
-      newLeftLon = -Math.PI;
-      newRightLon = Math.PI;
-    }
-    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return plane.evaluateIsZero(x, y, z) &&
-        (leftPlane.isWithin(x, y, z) ||
-            rightPlane.isWithin(x, y, z));
-  }
-
-  @Override
-  public double getRadius() {
-    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
-    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
-    // the distance to the right or left edge from the center.
-    final double topAngle = centerPoint.arcDistance(RHC);
-    final double bottomAngle = centerPoint.arcDistance(LHC);
-    return Math.max(topAngle, bottomAngle);
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    return centerPoint;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    // Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
-    // requires crossing into the right part of the other.  So intersection can ignore the left/right bounds.
-    return p.intersects(planetModel, plane, notablePoints, planePoints, bounds, eitherBound);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    bounds.isWide()
-      .addHorizontalPlane(planetModel, latitude, plane, eitherBound)
-      .addPoint(LHC)
-      .addPoint(RHC);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    if (path.intersects(plane, planePoints, eitherBound)) {
-      return OVERLAPS;
-    }
-
-    if (path.isWithin(centerPoint)) {
-      return CONTAINS;
-    }
-
-    return DISJOINT;
-  }
-
-  @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, eitherBound);
-    
-    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 GeoWideDegenerateHorizontalLine))
-      return false;
-    GeoWideDegenerateHorizontalLine other = (GeoWideDegenerateHorizontalLine) o;
-    return super.equals(other) && other.LHC.equals(LHC) && other.RHC.equals(RHC);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + LHC.hashCode();
-    result = 31 * result + RHC.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoWideDegenerateHorizontalLine: {planetmodel="+planetModel+", latitude=" + latitude + "(" + latitude * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightLon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
-  }
-
-  /** Membership implementation representing a wide cutoff (more than 180 degrees).
-   */
-  protected class EitherBound implements Membership {
-    /** Constructor.
-     */
-    public EitherBound() {
-    }
-
-    @Override
-    public boolean isWithin(final double x, final double y, final double z) {
-      return leftPlane.isWithin(x, y, z) || rightPlane.isWithin(x, y, z);
-    }
-  }
-}
-  
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideLongitudeSlice.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideLongitudeSlice.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideLongitudeSlice.java
deleted file mode 100755
index 64e4fa8..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideLongitudeSlice.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Bounding box wider than PI but limited on left and right sides (
- * left lon, right lon).
- *
- * @lucene.internal
- */
-public class GeoWideLongitudeSlice extends GeoBaseBBox {
-  /** The left longitude */
-  protected final double leftLon;
-  /** The right longitude */
-  protected final double rightLon;
-
-  /** The left plane */
-  protected final SidedPlane leftPlane;
-  /** The right plane */
-  protected final SidedPlane rightPlane;
-
-  /** Notable points for the shape */
-  protected final GeoPoint[] planePoints;
-
-  /** Center point for the shape */
-  protected final GeoPoint centerPoint;
-
-  /** A point on the edge of the shape */
-  protected final GeoPoint[] edgePoints; 
-
-  /**
-   * Accepts only values in the following ranges: lon: {@code -PI -> PI}.
-   * Horizantal angle must be greater than or equal to PI.
-   *@param planetModel is the planet model.
-   *@param leftLon is the left longitude.
-   *@param rightLon is the right longitude.
-   */
-  public GeoWideLongitudeSlice(final PlanetModel planetModel, final double leftLon, double rightLon) {
-    super(planetModel);
-    // Argument checking
-    if (leftLon < -Math.PI || leftLon > Math.PI)
-      throw new IllegalArgumentException("Left longitude out of range");
-    if (rightLon < -Math.PI || rightLon > Math.PI)
-      throw new IllegalArgumentException("Right longitude out of range");
-    double extent = rightLon - leftLon;
-    if (extent < 0.0) {
-      extent += 2.0 * Math.PI;
-    }
-    if (extent < Math.PI)
-      throw new IllegalArgumentException("Width of rectangle too small");
-
-    this.leftLon = leftLon;
-    this.rightLon = rightLon;
-
-    final double sinLeftLon = Math.sin(leftLon);
-    final double cosLeftLon = Math.cos(leftLon);
-    final double sinRightLon = Math.sin(rightLon);
-    final double cosRightLon = Math.cos(rightLon);
-
-    // Normalize
-    while (leftLon > rightLon) {
-      rightLon += Math.PI * 2.0;
-    }
-    final double middleLon = (leftLon + rightLon) * 0.5;
-    this.centerPoint = new GeoPoint(planetModel, 0.0, middleLon);
-
-    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
-    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
-    
-    this.planePoints = new GeoPoint[]{planetModel.NORTH_POLE, planetModel.SOUTH_POLE};
-    this.edgePoints = new GeoPoint[]{planetModel.NORTH_POLE};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    // Figuring out when we escalate to a special case requires some prefiguring
-    double currentLonSpan = rightLon - leftLon;
-    if (currentLonSpan < 0.0)
-      currentLonSpan += Math.PI * 2.0;
-    double newLeftLon = leftLon - angle;
-    double newRightLon = rightLon + angle;
-    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
-      newLeftLon = -Math.PI;
-      newRightLon = Math.PI;
-    }
-    return GeoBBoxFactory.makeGeoBBox(planetModel, Math.PI * 0.5, -Math.PI * 0.5, newLeftLon, newRightLon);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return leftPlane.isWithin(x, y, z) ||
-        rightPlane.isWithin(x, y, z);
-  }
-
-  @Override
-  public double getRadius() {
-    // Compute the extent and divide by two
-    double extent = rightLon - leftLon;
-    if (extent < 0.0)
-      extent += Math.PI * 2.0;
-    return Math.max(Math.PI * 0.5, extent * 0.5);
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    return centerPoint;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    // Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
-    // requires crossing into the right part of the other.  So intersection can ignore the left/right bounds.
-    return p.intersects(planetModel, leftPlane, notablePoints, planePoints, bounds) ||
-        p.intersects(planetModel, rightPlane, notablePoints, planePoints, bounds);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    bounds.isWide()
-      .addVerticalPlane(planetModel, leftLon, leftPlane)
-      .addVerticalPlane(planetModel, rightLon, rightPlane)
-      .addPoint(planetModel.NORTH_POLE)
-      .addPoint(planetModel.SOUTH_POLE);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    final int insideRectangle = isShapeInsideBBox(path);
-    if (insideRectangle == SOME_INSIDE)
-      return OVERLAPS;
-
-    final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
-
-    if (insideRectangle == ALL_INSIDE && insideShape)
-      return OVERLAPS;
-
-    if (path.intersects(leftPlane, planePoints) ||
-        path.intersects(rightPlane, planePoints))
-      return OVERLAPS;
-
-    if (insideRectangle == ALL_INSIDE)
-      return WITHIN;
-
-    if (insideShape)
-      return CONTAINS;
-
-    return DISJOINT;
-  }
-
-  @Override
-  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
-    // Because the rectangle exceeds 180 degrees, it is safe to compute the horizontally 
-    // unbounded distance to both the left and the right and only take the minimum of the two.
-    final double leftDistance = distanceStyle.computeDistance(planetModel, leftPlane, x,y,z);
-    final double rightDistance = distanceStyle.computeDistance(planetModel, rightPlane, x,y,z);
-    
-    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(leftDistance, rightDistance),
-      Math.min(northDistance, southDistance));
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof GeoWideLongitudeSlice))
-      return false;
-    GeoWideLongitudeSlice other = (GeoWideLongitudeSlice) o;
-    return super.equals(other) && other.leftLon == leftLon && other.rightLon == rightLon;
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    long temp = Double.doubleToLongBits(leftLon);
-    result = 31 * result + (int) (temp ^ (temp >>> 32));
-    temp = Double.doubleToLongBits(rightLon);
-    result = 31 * result + (int) (temp ^ (temp >>> 32));
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoWideLongitudeSlice: {planetmodel="+planetModel+", leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
-  }
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideNorthRectangle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideNorthRectangle.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideNorthRectangle.java
deleted file mode 100644
index 86de584..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideNorthRectangle.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Bounding box wider than PI but limited on three sides (
- * bottom lat, left lon, right lon).
- *
- * @lucene.internal
- */
-public class GeoWideNorthRectangle extends GeoBaseBBox {
-  /** Bottom latitude */
-  protected final double bottomLat;
-  /** Left longitude */
-  protected final double leftLon;
-  /** Right longitude */
-  protected final double rightLon;
-
-  /** The cosine of the middle latitude */
-  protected final double cosMiddleLat;
-
-  /** The lower right hand corner point */
-  protected final GeoPoint LRHC;
-  /** The lower left hand corner point */
-  protected final GeoPoint LLHC;
-
-  /** The bottom plane */
-  protected final SidedPlane bottomPlane;
-  /** The left plane */
-  protected final SidedPlane leftPlane;
-  /** The right plane */
-  protected final SidedPlane rightPlane;
-
-  /** Notable points for the bottom plane */
-  protected final GeoPoint[] bottomPlanePoints;
-  /** Notable points for the left plane */
-  protected final GeoPoint[] leftPlanePoints;
-  /** Notable points for the right plane */
-  protected final GeoPoint[] rightPlanePoints;
-
-  /** Center point */
-  protected final GeoPoint centerPoint;
-
-  /** Composite left/right bounds */
-  protected final EitherBound eitherBound;
-
-  /** A point on the edge */
-  protected final GeoPoint[] edgePoints;
-
-  /**
-   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}.
-   * Horizontal angle must be greater than or equal to PI.
-   */
-  public GeoWideNorthRectangle(final PlanetModel planetModel, final double bottomLat, final double leftLon, double rightLon) {
-    super(planetModel);
-    // Argument checking
-    if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
-      throw new IllegalArgumentException("Bottom latitude out of range");
-    if (leftLon < -Math.PI || leftLon > Math.PI)
-      throw new IllegalArgumentException("Left longitude out of range");
-    if (rightLon < -Math.PI || rightLon > Math.PI)
-      throw new IllegalArgumentException("Right longitude out of range");
-    double extent = rightLon - leftLon;
-    if (extent < 0.0) {
-      extent += 2.0 * Math.PI;
-    }
-    if (extent < Math.PI)
-      throw new IllegalArgumentException("Width of rectangle too small");
-
-    this.bottomLat = bottomLat;
-    this.leftLon = leftLon;
-    this.rightLon = rightLon;
-
-    final double sinBottomLat = Math.sin(bottomLat);
-    final double cosBottomLat = Math.cos(bottomLat);
-    final double sinLeftLon = Math.sin(leftLon);
-    final double cosLeftLon = Math.cos(leftLon);
-    final double sinRightLon = Math.sin(rightLon);
-    final double cosRightLon = Math.cos(rightLon);
-
-    // Now build the four points
-    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);
-    this.cosMiddleLat = Math.cos(middleLat);
-    // Normalize
-    while (leftLon > rightLon) {
-      rightLon += Math.PI * 2.0;
-    }
-    final double middleLon = (leftLon + rightLon) * 0.5;
-    final double sinMiddleLon = Math.sin(middleLon);
-    final double cosMiddleLon = Math.cos(middleLon);
-
-    this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
-
-    this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
-    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
-    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
-
-    this.bottomPlanePoints = new GeoPoint[]{LLHC, LRHC};
-    this.leftPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LLHC};
-    this.rightPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LRHC};
-
-    this.eitherBound = new EitherBound();
-    this.edgePoints = new GeoPoint[]{planetModel.NORTH_POLE};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    final double newTopLat = Math.PI * 0.5;
-    final double newBottomLat = bottomLat - angle;
-    // Figuring out when we escalate to a special case requires some prefiguring
-    double currentLonSpan = rightLon - leftLon;
-    if (currentLonSpan < 0.0)
-      currentLonSpan += Math.PI * 2.0;
-    double newLeftLon = leftLon - angle;
-    double newRightLon = rightLon + angle;
-    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
-      newLeftLon = -Math.PI;
-      newRightLon = Math.PI;
-    }
-    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return
-        bottomPlane.isWithin(x, y, z) &&
-            (leftPlane.isWithin(x, y, z) ||
-                rightPlane.isWithin(x, y, z));
-  }
-
-  @Override
-  public double getRadius() {
-    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
-    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
-    // the distance to the right or left edge from the center.
-    final double centerAngle = (rightLon - (rightLon + leftLon) * 0.5) * cosMiddleLat;
-    final double bottomAngle = centerPoint.arcDistance(LLHC);
-    return Math.max(centerAngle, bottomAngle);
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    return centerPoint;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    // Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
-    // requires crossing into the right part of the other.  So intersection can ignore the left/right bounds.
-    return
-        p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, eitherBound) ||
-            p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, bottomPlane) ||
-            p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, bottomPlane);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    bounds.isWide()
-      .addHorizontalPlane(planetModel, bottomLat, bottomPlane, eitherBound)
-      .addVerticalPlane(planetModel, leftLon, leftPlane, bottomPlane)
-      .addVerticalPlane(planetModel, rightLon, rightPlane, bottomPlane)
-      .addPoint(LLHC).addPoint(LRHC).addPoint(planetModel.NORTH_POLE);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    //System.err.println(this+" comparing to "+path);
-    final int insideRectangle = isShapeInsideBBox(path);
-    if (insideRectangle == SOME_INSIDE) {
-      //System.err.println(" some inside");
-      return OVERLAPS;
-    }
-
-    final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
-
-    if (insideRectangle == ALL_INSIDE && insideShape) {
-      //System.err.println(" both inside each other");
-      return OVERLAPS;
-    }
-
-    if (
-        path.intersects(bottomPlane, bottomPlanePoints, eitherBound) ||
-            path.intersects(leftPlane, leftPlanePoints, bottomPlane) ||
-            path.intersects(rightPlane, rightPlanePoints, bottomPlane)) {
-      //System.err.println(" edges intersect");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE) {
-      //System.err.println(" shape inside rectangle");
-      return WITHIN;
-    }
-
-    if (insideShape) {
-      //System.err.println(" rectangle inside shape");
-      return CONTAINS;
-    }
-
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @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, eitherBound);
-    // Because the rectangle exceeds 180 degrees, it is safe to compute the horizontally 
-    // unbounded distance to both the left and the right and only take the minimum of the two.
-    final double leftDistance = distanceStyle.computeDistance(planetModel, leftPlane, x,y,z, bottomPlane);
-    final double rightDistance = distanceStyle.computeDistance(planetModel, rightPlane, x,y,z, bottomPlane);
-    
-    final double LRHCDistance = distanceStyle.computeDistance(LRHC, x,y,z);
-    final double LLHCDistance = distanceStyle.computeDistance(LLHC, x,y,z);
-    
-    return Math.min(
-      Math.min(
-        bottomDistance,
-        Math.min(leftDistance, rightDistance)),
-      Math.min(LRHCDistance, LLHCDistance));
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof GeoWideNorthRectangle))
-      return false;
-    GeoWideNorthRectangle other = (GeoWideNorthRectangle) o;
-    return super.equals(other) && other.LLHC.equals(LLHC) && other.LRHC.equals(LRHC);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + LLHC.hashCode();
-    result = 31 * result + LRHC.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoWideNorthRectangle: {planetmodel="+planetModel+", bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
-  }
-
-  /** Membership implementation representing a wide (more than 180 degree) bound.
-   */
-  protected class EitherBound implements Membership {
-    /** Constructor.
-     */
-    public EitherBound() {
-    }
-
-    @Override
-    public boolean isWithin(final Vector v) {
-      return leftPlane.isWithin(v) || rightPlane.isWithin(v);
-    }
-
-    @Override
-    public boolean isWithin(final double x, final double y, final double z) {
-      return leftPlane.isWithin(x, y, z) || rightPlane.isWithin(x, y, z);
-    }
-  }
-}
-  
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideRectangle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideRectangle.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideRectangle.java
deleted file mode 100755
index 68397bb..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideRectangle.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Bounding box wider than PI but limited on four sides (top lat,
- * bottom lat, left lon, right lon).
- *
- * @lucene.internal
- */
-public class GeoWideRectangle extends GeoBaseBBox {
-  /** The top latitude */
-  protected final double topLat;
-  /** The bottom latitude */
-  protected final double bottomLat;
-  /** The left longitude */
-  protected final double leftLon;
-  /** The right longitude */
-  protected final double rightLon;
-
-  /** Cosine of the middle latitude */
-  protected final double cosMiddleLat;
-
-  /** Upper left hand corner point */
-  protected final GeoPoint ULHC;
-  /** Lower right hand corner point */
-  protected final GeoPoint URHC;
-  /** Lower right hand corner point */
-  protected final GeoPoint LRHC;
-  /** Lower left hand corner point */
-  protected final GeoPoint LLHC;
-
-  /** Top plane */
-  protected final SidedPlane topPlane;
-  /** Bottom plane */
-  protected final SidedPlane bottomPlane;
-  /** Left plane */
-  protected final SidedPlane leftPlane;
-  /** Right plane */
-  protected final SidedPlane rightPlane;
-
-  /** Top plane's notable points */
-  protected final GeoPoint[] topPlanePoints;
-  /** Bottom plane's notable points */
-  protected final GeoPoint[] bottomPlanePoints;
-  /** Left plane's notable points */
-  protected final GeoPoint[] leftPlanePoints;
-  /** Right plane's notable points */
-  protected final GeoPoint[] rightPlanePoints;
-
-  /** Center point */
-  protected final GeoPoint centerPoint;
-
-  /** Combined left/right bounds */
-  protected final EitherBound eitherBound;
-
-  /** A point on the edge */
-  protected final GeoPoint[] edgePoints;
-
-  /**
-   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}.
-   * Horizontal angle must be greater than or equal to PI.
-   */
-  public GeoWideRectangle(final PlanetModel planetModel, final double topLat, final double bottomLat, final double leftLon, double rightLon) {
-    super(planetModel);
-    // Argument checking
-    if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
-      throw new IllegalArgumentException("Top latitude out of range");
-    if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
-      throw new IllegalArgumentException("Bottom latitude out of range");
-    if (topLat < bottomLat)
-      throw new IllegalArgumentException("Top latitude less than bottom latitude");
-    if (leftLon < -Math.PI || leftLon > Math.PI)
-      throw new IllegalArgumentException("Left longitude out of range");
-    if (rightLon < -Math.PI || rightLon > Math.PI)
-      throw new IllegalArgumentException("Right longitude out of range");
-    double extent = rightLon - leftLon;
-    if (extent < 0.0) {
-      extent += 2.0 * Math.PI;
-    }
-    if (extent < Math.PI)
-      throw new IllegalArgumentException("Width of rectangle too small");
-
-    this.topLat = topLat;
-    this.bottomLat = bottomLat;
-    this.leftLon = leftLon;
-    this.rightLon = rightLon;
-
-    final double sinTopLat = Math.sin(topLat);
-    final double cosTopLat = Math.cos(topLat);
-    final double sinBottomLat = Math.sin(bottomLat);
-    final double cosBottomLat = Math.cos(bottomLat);
-    final double sinLeftLon = Math.sin(leftLon);
-    final double cosLeftLon = Math.cos(leftLon);
-    final double sinRightLon = Math.sin(rightLon);
-    final double cosRightLon = Math.cos(rightLon);
-
-    // Now build the four points
-    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);
-    this.cosMiddleLat = Math.cos(middleLat);
-    // Normalize
-    while (leftLon > rightLon) {
-      rightLon += Math.PI * 2.0;
-    }
-    final double middleLon = (leftLon + rightLon) * 0.5;
-    final double sinMiddleLon = Math.sin(middleLon);
-    final double cosMiddleLon = Math.cos(middleLon);
-
-    this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
-
-    this.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
-    this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
-    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
-    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
-
-    this.topPlanePoints = new GeoPoint[]{ULHC, URHC};
-    this.bottomPlanePoints = new GeoPoint[]{LLHC, LRHC};
-    this.leftPlanePoints = new GeoPoint[]{ULHC, LLHC};
-    this.rightPlanePoints = new GeoPoint[]{URHC, LRHC};
-
-    this.eitherBound = new EitherBound();
-
-    this.edgePoints = new GeoPoint[]{ULHC};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    final double newTopLat = topLat + angle;
-    final double newBottomLat = bottomLat - angle;
-    // Figuring out when we escalate to a special case requires some prefiguring
-    double currentLonSpan = rightLon - leftLon;
-    if (currentLonSpan < 0.0)
-      currentLonSpan += Math.PI * 2.0;
-    double newLeftLon = leftLon - angle;
-    double newRightLon = rightLon + angle;
-    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
-      newLeftLon = -Math.PI;
-      newRightLon = Math.PI;
-    }
-    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return topPlane.isWithin(x, y, z) &&
-        bottomPlane.isWithin(x, y, z) &&
-        (leftPlane.isWithin(x, y, z) ||
-            rightPlane.isWithin(x, y, z));
-  }
-
-  @Override
-  public double getRadius() {
-    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
-    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
-    // the distance to the right or left edge from the center.
-    final double centerAngle = (rightLon - (rightLon + leftLon) * 0.5) * cosMiddleLat;
-    final double topAngle = centerPoint.arcDistance(URHC);
-    final double bottomAngle = centerPoint.arcDistance(LLHC);
-    return Math.max(centerAngle, Math.max(topAngle, bottomAngle));
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  /**
-   * Returns the center of a circle into which the area will be inscribed.
-   *
-   * @return the center.
-   */
-  @Override
-  public GeoPoint getCenter() {
-    return centerPoint;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    // Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
-    // requires crossing into the right part of the other.  So intersection can ignore the left/right bounds.
-    return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, bottomPlane, eitherBound) ||
-        p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, topPlane, eitherBound) ||
-        p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, topPlane, bottomPlane) ||
-        p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, topPlane, bottomPlane);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    bounds.isWide()
-      .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
-  public int getRelationship(final GeoShape path) {
-    //System.err.println(this+" comparing to "+path);
-    final int insideRectangle = isShapeInsideBBox(path);
-    if (insideRectangle == SOME_INSIDE) {
-      //System.err.println(" some inside");
-      return OVERLAPS;
-    }
-
-    final boolean insideShape = path.isWithin(ULHC);
-
-    if (insideRectangle == ALL_INSIDE && insideShape) {
-      //System.err.println(" both inside each other");
-      return OVERLAPS;
-    }
-
-    if (path.intersects(topPlane, topPlanePoints, bottomPlane, eitherBound) ||
-        path.intersects(bottomPlane, bottomPlanePoints, topPlane, eitherBound) ||
-        path.intersects(leftPlane, leftPlanePoints, topPlane, bottomPlane) ||
-        path.intersects(rightPlane, rightPlanePoints, topPlane, bottomPlane)) {
-      //System.err.println(" edges intersect");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE) {
-      //System.err.println(" shape inside rectangle");
-      return WITHIN;
-    }
-
-    if (insideShape) {
-      //System.err.println(" rectangle inside shape");
-      return CONTAINS;
-    }
-
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @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, eitherBound);
-    final double bottomDistance = distanceStyle.computeDistance(planetModel, bottomPlane, x,y,z, topPlane, eitherBound);
-    // Because the rectangle exceeds 180 degrees, it is safe to compute the horizontally 
-    // unbounded distance to both the left and the right and only take the minimum of the two.
-    final double leftDistance = distanceStyle.computeDistance(planetModel, leftPlane, x,y,z, topPlane, bottomPlane);
-    final double rightDistance = distanceStyle.computeDistance(planetModel, rightPlane, x,y,z, topPlane, bottomPlane);
-    
-    final double ULHCDistance = distanceStyle.computeDistance(ULHC, x,y,z);
-    final double URHCDistance = distanceStyle.computeDistance(URHC, x,y,z);
-    final double LRHCDistance = distanceStyle.computeDistance(LRHC, x,y,z);
-    final double LLHCDistance = distanceStyle.computeDistance(LLHC, x,y,z);
-    
-    return Math.min(
-      Math.min(
-        Math.min(topDistance, bottomDistance),
-        Math.min(leftDistance, rightDistance)),
-      Math.min(
-        Math.min(ULHCDistance, URHCDistance),
-        Math.min(LRHCDistance, LLHCDistance)));
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof GeoWideRectangle))
-      return false;
-    GeoWideRectangle other = (GeoWideRectangle) o;
-    return super.equals(other) && other.ULHC.equals(ULHC) && other.LRHC.equals(LRHC);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + ULHC.hashCode();
-    result = 31 * result + LRHC.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoWideRectangle: {planetmodel=" + planetModel + ", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
-  }
-
-  /** A membership implementation representing a wide (more than 180) left/right bound.
-   */
-  protected class EitherBound implements Membership {
-    /** Constructor.
-      */
-    public EitherBound() {
-    }
-
-    @Override
-    public boolean isWithin(final Vector v) {
-      return leftPlane.isWithin(v) || rightPlane.isWithin(v);
-    }
-
-    @Override
-    public boolean isWithin(final double x, final double y, final double z) {
-      return leftPlane.isWithin(x, y, z) || rightPlane.isWithin(x, y, z);
-    }
-  }
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideSouthRectangle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideSouthRectangle.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideSouthRectangle.java
deleted file mode 100644
index 8bd7220..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideSouthRectangle.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Bounding box wider than PI but limited on three sides (top lat,
- * left lon, right lon).
- *
- * @lucene.internal
- */
-public class GeoWideSouthRectangle extends GeoBaseBBox {
-  /** Top latitude of rect */
-  protected final double topLat;
-  /** Left longitude of rect */
-  protected final double leftLon;
-  /** Right longitude of rect */
-  protected final double rightLon;
-
-  /** Cosine of middle latitude */
-  protected final double cosMiddleLat;
-
-  /** Upper left hand corner */
-  protected final GeoPoint ULHC;
-  /** Upper right hand corner */
-  protected final GeoPoint URHC;
-
-  /** The top plane */
-  protected final SidedPlane topPlane;
-  /** The left plane */
-  protected final SidedPlane leftPlane;
-  /** The right plane */
-  protected final SidedPlane rightPlane;
-
-  /** Notable points for top plane */
-  protected final GeoPoint[] topPlanePoints;
-  /** Notable points for left plane */
-  protected final GeoPoint[] leftPlanePoints;
-  /** Notable points for right plane */
-  protected final GeoPoint[] rightPlanePoints;
-
-  /** Center point */
-  protected final GeoPoint centerPoint;
-
-  /** Left/right bounds */
-  protected final EitherBound eitherBound;
-
-  /** A point on the edge */
-  protected final GeoPoint[] edgePoints;
-
-  /**
-   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}.
-   * Horizontal angle must be greater than or equal to PI.
-   */
-  public GeoWideSouthRectangle(final PlanetModel planetModel, final double topLat, final double leftLon, double rightLon) {
-    super(planetModel);
-    // Argument checking
-    if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
-      throw new IllegalArgumentException("Top latitude out of range");
-    if (leftLon < -Math.PI || leftLon > Math.PI)
-      throw new IllegalArgumentException("Left longitude out of range");
-    if (rightLon < -Math.PI || rightLon > Math.PI)
-      throw new IllegalArgumentException("Right longitude out of range");
-    double extent = rightLon - leftLon;
-    if (extent < 0.0) {
-      extent += 2.0 * Math.PI;
-    }
-    if (extent < Math.PI)
-      throw new IllegalArgumentException("Width of rectangle too small");
-
-    this.topLat = topLat;
-    this.leftLon = leftLon;
-    this.rightLon = rightLon;
-
-    final double sinTopLat = Math.sin(topLat);
-    final double cosTopLat = Math.cos(topLat);
-    final double sinLeftLon = Math.sin(leftLon);
-    final double cosLeftLon = Math.cos(leftLon);
-    final double sinRightLon = Math.sin(rightLon);
-    final double cosRightLon = Math.cos(rightLon);
-
-    // Now build the four points
-    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);
-    this.cosMiddleLat = Math.cos(middleLat);
-    // Normalize
-    while (leftLon > rightLon) {
-      rightLon += Math.PI * 2.0;
-    }
-    final double middleLon = (leftLon + rightLon) * 0.5;
-    final double sinMiddleLon = Math.sin(middleLon);
-    final double cosMiddleLon = Math.cos(middleLon);
-
-    this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
-
-    this.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
-    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
-    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
-
-    this.topPlanePoints = new GeoPoint[]{ULHC, URHC};
-    this.leftPlanePoints = new GeoPoint[]{ULHC, planetModel.SOUTH_POLE};
-    this.rightPlanePoints = new GeoPoint[]{URHC, planetModel.SOUTH_POLE};
-
-    this.eitherBound = new EitherBound();
-    
-    this.edgePoints = new GeoPoint[]{planetModel.SOUTH_POLE};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    final double newTopLat = topLat + angle;
-    final double newBottomLat = -Math.PI * 0.5;
-    // Figuring out when we escalate to a special case requires some prefiguring
-    double currentLonSpan = rightLon - leftLon;
-    if (currentLonSpan < 0.0)
-      currentLonSpan += Math.PI * 2.0;
-    double newLeftLon = leftLon - angle;
-    double newRightLon = rightLon + angle;
-    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
-      newLeftLon = -Math.PI;
-      newRightLon = Math.PI;
-    }
-    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return topPlane.isWithin(x, y, z) &&
-        (leftPlane.isWithin(x, y, z) ||
-            rightPlane.isWithin(x, y, z));
-  }
-
-  @Override
-  public double getRadius() {
-    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
-    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
-    // the distance to the right or left edge from the center.
-    final double centerAngle = (rightLon - (rightLon + leftLon) * 0.5) * cosMiddleLat;
-    final double topAngle = centerPoint.arcDistance(URHC);
-    return Math.max(centerAngle, topAngle);
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    return centerPoint;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    // Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
-    // requires crossing into the right part of the other.  So intersection can ignore the left/right bounds.
-    return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, eitherBound) ||
-        p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, topPlane) ||
-        p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, topPlane);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    bounds.isWide()
-      .addHorizontalPlane(planetModel, topLat, topPlane, eitherBound)
-      .addVerticalPlane(planetModel, rightLon, rightPlane, topPlane)
-      .addVerticalPlane(planetModel, leftLon, leftPlane, topPlane)
-      .addPoint(ULHC).addPoint(URHC).addPoint(planetModel.SOUTH_POLE);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    //System.err.println(this+" comparing to "+path);
-    final int insideRectangle = isShapeInsideBBox(path);
-    if (insideRectangle == SOME_INSIDE) {
-      //System.err.println(" some inside");
-      return OVERLAPS;
-    }
-
-    final boolean insideShape = path.isWithin(planetModel.SOUTH_POLE);
-
-    if (insideRectangle == ALL_INSIDE && insideShape) {
-      //System.err.println(" both inside each other");
-      return OVERLAPS;
-    }
-
-    if (path.intersects(topPlane, topPlanePoints, eitherBound) ||
-        path.intersects(leftPlane, leftPlanePoints, topPlane) ||
-        path.intersects(rightPlane, rightPlanePoints, topPlane)) {
-      //System.err.println(" edges intersect");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE) {
-      //System.err.println(" shape inside rectangle");
-      return WITHIN;
-    }
-
-    if (insideShape) {
-      //System.err.println(" rectangle inside shape");
-      return CONTAINS;
-    }
-
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @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, eitherBound);
-    // Because the rectangle exceeds 180 degrees, it is safe to compute the horizontally 
-    // unbounded distance to both the left and the right and only take the minimum of the two.
-    final double leftDistance = distanceStyle.computeDistance(planetModel, leftPlane, x,y,z, topPlane);
-    final double rightDistance = distanceStyle.computeDistance(planetModel, rightPlane, x,y,z, topPlane);
-    
-    final double ULHCDistance = distanceStyle.computeDistance(ULHC, x,y,z);
-    final double URHCDistance = distanceStyle.computeDistance(URHC, x,y,z);
-    
-    return Math.min(
-      Math.min(
-        topDistance,
-        Math.min(leftDistance, rightDistance)),
-      Math.min(ULHCDistance, URHCDistance));
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof GeoWideSouthRectangle))
-      return false;
-    GeoWideSouthRectangle other = (GeoWideSouthRectangle) o;
-    return super.equals(o) && other.ULHC.equals(ULHC) && other.URHC.equals(URHC);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + ULHC.hashCode();
-    result = 31 * result + URHC.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoWideSouthRectangle: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
-  }
-
-  /** Membership implementation representing width more than 180.
-   */
-  protected class EitherBound implements Membership {
-    /** Constructor.
-     */
-    public EitherBound() {
-    }
-
-    @Override
-    public boolean isWithin(final Vector v) {
-      return leftPlane.isWithin(v) || rightPlane.isWithin(v);
-    }
-
-    @Override
-    public boolean isWithin(final double x, final double y, final double z) {
-      return leftPlane.isWithin(x, y, z) || rightPlane.isWithin(x, y, z);
-    }
-  }
-}
-  
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWorld.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWorld.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWorld.java
deleted file mode 100755
index 35ec4ae..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWorld.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Bounding box including the entire world.
- *
- * @lucene.internal
- */
-public class GeoWorld extends GeoBaseBBox {
-  /** No points on the edge of the shape */
-  protected final static GeoPoint[] edgePoints = new GeoPoint[0];
-  /** Point in the middle of the world */
-  protected final GeoPoint originPoint;
-  
-  /** Constructor.
-   *@param planetModel is the planet model.
-   */
-  public GeoWorld(final PlanetModel planetModel) {
-    super(planetModel);
-    originPoint = new GeoPoint(planetModel.ab, 1.0, 0.0, 0.0);
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    return this;
-  }
-
-  @Override
-  public double getRadius() {
-    return Math.PI;
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    // Totally arbitrary
-    return originPoint;
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return true;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    return false;
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    // Unnecessary
-    //bounds.noLongitudeBound().noTopLatitudeBound().noBottomLatitudeBound();
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    if (path.getEdgePoints().length > 0)
-      // Path is always within the world
-      return WITHIN;
-
-    return OVERLAPS;
-  }
-
-  @Override
-  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
-    return 0.0;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof GeoWorld))
-      return false;
-    return super.equals(o);
-  }
-
-  @Override
-  public int hashCode() {
-    return super.hashCode();
-  }
-
-  @Override
-  public String toString() {
-    return "GeoWorld: {planetmodel="+planetModel+"}";
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LatLonBounds.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LatLonBounds.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LatLonBounds.java
deleted file mode 100644
index 6478e0c..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LatLonBounds.java
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * 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() {
-    return noLongitudeBound();
-  }
-
-  @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() {
-    noLongitudeBound = true;
-    leftLongitude = null;
-    rightLongitude = null;
-    return this;
-  }
-
-  @Override
-  public Bounds noTopLatitudeBound() {
-    noTopLatitudeBound = true;
-    maxLatitude = null;
-    return this;
-  }
-
-  @Override
-  public Bounds noBottomLatitudeBound() {
-    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 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;
-    }
-  }
-
-}


[38/50] [abbrv] lucene-solr git commit: LUCENE-7083: default points merge logic should not ask a reader to merge points on a field that doesn't exist in that segment

Posted by no...@apache.org.
LUCENE-7083: default points merge logic should not ask a reader to merge points on a field that doesn't exist in that segment


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

Branch: refs/heads/apiv2
Commit: 2cac33a5ce7b64713eba6e22d5f7c9122ab8eafe
Parents: 9393a31
Author: Mike McCandless <mi...@apache.org>
Authored: Tue Mar 8 13:28:28 2016 -0500
Committer: Mike McCandless <mi...@apache.org>
Committed: Tue Mar 8 13:28:28 2016 -0500

----------------------------------------------------------------------
 .../org/apache/lucene/codecs/PointsWriter.java  |  6 ++++++
 .../org/apache/lucene/index/IndexWriter.java    |  1 +
 .../apache/lucene/index/TestPointValues.java    | 20 ++++++++++++++++++++
 3 files changed, 27 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/2cac33a5/lucene/core/src/java/org/apache/lucene/codecs/PointsWriter.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/PointsWriter.java b/lucene/core/src/java/org/apache/lucene/codecs/PointsWriter.java
index 56689ec..53db281 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/PointsWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/PointsWriter.java
@@ -54,6 +54,12 @@ public abstract class PointsWriter implements Closeable {
                        // This segment has no points
                        continue;
                      }
+                     FieldInfo readerFieldInfo = mergeState.fieldInfos[i].fieldInfo(fieldName);
+                     if (readerFieldInfo == null) {
+                       // This segment never saw this field
+                       continue;
+                     }
+
                      MergeState.DocMap docMap = mergeState.docMaps[i];
                      int docBase = mergeState.docBase[i];
                      pointsReader.intersect(fieldInfo.name,

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/2cac33a5/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java b/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
index 57ce3dd..66a0e73 100644
--- a/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
@@ -4116,6 +4116,7 @@ public class IndexWriter implements Closeable, TwoPhaseCommit, Accountable {
                              (mergeState.mergeFieldInfos.hasDocValues() ? "docValues" : "no docValues") + "; " + 
                              (mergeState.mergeFieldInfos.hasProx() ? "prox" : "no prox") + "; " + 
                              (mergeState.mergeFieldInfos.hasProx() ? "freqs" : "no freqs") + "; " +
+                             (mergeState.mergeFieldInfos.hasPointValues() ? "points" : "no points") + "; " +
                              String.format(Locale.ROOT,
                                            "%.1f sec (%.1f sec stopped, %.1f sec paused) to merge segment [%.2f MB, %.2f MB/sec]",
                                            sec,

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/2cac33a5/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java b/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
index 7231b1a..9ced11a 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
@@ -39,6 +39,7 @@ import org.apache.lucene.index.PointValues.IntersectVisitor;
 import org.apache.lucene.index.PointValues.Relation;
 import org.apache.lucene.index.PointValues;
 import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.FSDirectory;
 import org.apache.lucene.util.IOUtils;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
@@ -562,4 +563,23 @@ public class TestPointValues extends LuceneTestCase {
     r.close();
     dir.close();
   }
+
+  public void testPointsFieldMissingFromOneSegment() throws Exception {
+    Directory dir = FSDirectory.open(createTempDir());
+    IndexWriterConfig iwc = new IndexWriterConfig(null);
+    IndexWriter w = new IndexWriter(dir, iwc);
+    Document doc = new Document();
+    doc.add(new StringField("id", "0", Field.Store.NO));
+    doc.add(new IntPoint("int0", 0));
+    w.addDocument(doc);
+    w.commit();
+
+    doc = new Document();
+    doc.add(new IntPoint("int1", 17));
+    w.addDocument(doc);
+    w.forceMerge(1);
+
+    w.close();
+    dir.close();
+  }
 }


[17/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XdYZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XdYZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XdYZSolid.java
deleted file mode 100644
index f6a2fa3..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XdYZSolid.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in Y
- *
- * @lucene.internal
- */
-public class XdYZSolid extends BaseXYZSolid {
-
-  /** Min-X plane */
-  protected final SidedPlane minXPlane;
-  /** Max-X plane */
-  protected final SidedPlane maxXPlane;
-  /** Y plane */
-  protected final Plane yPlane;
-  /** Min-Z plane */
-  protected final SidedPlane minZPlane;
-  /** Max-Z plane */
-  protected final SidedPlane maxZPlane;
-  
-  /** These are the edge points of the shape, which are defined to be at least one point on
-   * each surface area boundary.  In the case of a solid, this includes points which represent
-   * the intersection of XYZ bounding planes and the planet, as well as points representing
-   * the intersection of single bounding planes with the planet itself.
-   */
-  protected final GeoPoint[] edgePoints;
-
-  /** Notable points for YPlane */
-  protected final GeoPoint[] notableYPoints;
-
-  /**
-   * Sole constructor
-   *
-   *@param planetModel is the planet model.
-   *@param minX is the minimum X value.
-   *@param maxX is the maximum X value.
-   *@param Y is the Y value.
-   *@param minZ is the minimum Z value.
-   *@param maxZ is the maximum Z value.
-   */
-  public XdYZSolid(final PlanetModel planetModel,
-    final double minX,
-    final double maxX,
-    final double Y,
-    final double minZ,
-    final double maxZ) {
-    super(planetModel);
-    // Argument checking
-    if (maxX - minX < Vector.MINIMUM_RESOLUTION)
-      throw new IllegalArgumentException("X values in wrong order or identical");
-    if (maxZ - minZ < Vector.MINIMUM_RESOLUTION)
-      throw new IllegalArgumentException("Z values in wrong order or identical");
-
-    final double worldMinY = planetModel.getMinimumYValue();
-    final double worldMaxY = planetModel.getMaximumYValue();
-    
-    // Construct the planes
-    minXPlane = new SidedPlane(maxX,0.0,0.0,xUnitVector,-minX);
-    maxXPlane = new SidedPlane(minX,0.0,0.0,xUnitVector,-maxX);
-    yPlane = new Plane(yUnitVector,-Y);
-    minZPlane = new SidedPlane(0.0,0.0,maxZ,zUnitVector,-minZ);
-    maxZPlane = new SidedPlane(0.0,0.0,minZ,zUnitVector,-maxZ);
-      
-    // We need at least one point on the planet surface for each manifestation of the shape.
-    // There can be up to 2 (on opposite sides of the world).  But we have to go through
-    // 4 combinations of adjacent planes in order to find out if any have 2 intersection solution.
-    // Typically, this requires 4 square root operations. 
-    final GeoPoint[] minXY = minXPlane.findIntersections(planetModel,yPlane,maxXPlane,minZPlane,maxZPlane);
-    final GeoPoint[] maxXY = maxXPlane.findIntersections(planetModel,yPlane,minXPlane,minZPlane,maxZPlane);
-    final GeoPoint[] YminZ = yPlane.findIntersections(planetModel,minZPlane,maxZPlane,minXPlane,maxXPlane);
-    final GeoPoint[] YmaxZ = yPlane.findIntersections(planetModel,maxZPlane,minZPlane,minXPlane,maxXPlane);
-      
-    notableYPoints = glueTogether(minXY, maxXY, YminZ, YmaxZ);
-
-    // Now, compute the edge points.
-    // This is the trickiest part of setting up an XYZSolid.  We've computed intersections already, so
-    // we'll start there.  We know that at most there will be two disconnected shapes on the planet surface.
-    // But there's also a case where exactly one plane slices through the world, and none of the bounding plane
-    // intersections do.  Thus, if we don't find any of the edge intersection cases, we have to look for that last case.
-      
-    // We need to look at single-plane/world intersections.
-    // We detect these by looking at the world model and noting its x, y, and z bounds.
-    // The cases we are looking for are when the four corner points for any given
-    // plane are all outside of the world, AND that plane intersects the world.
-    // There are four corner points all told; we must evaluate these WRT the planet surface.
-    final boolean minXYminZ = planetModel.pointOutside(minX, Y, minZ);
-    final boolean minXYmaxZ = planetModel.pointOutside(minX, Y, maxZ);
-    final boolean maxXYminZ = planetModel.pointOutside(maxX, Y, minZ);
-    final boolean maxXYmaxZ = planetModel.pointOutside(maxX, Y, maxZ);
-
-    final GeoPoint[] yEdges;
-    if (Y - worldMinY >= -Vector.MINIMUM_RESOLUTION && Y - worldMaxY <= Vector.MINIMUM_RESOLUTION &&
-      minX < 0.0 && maxX > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
-      minXYminZ && minXYmaxZ && maxXYminZ && maxXYmaxZ) {
-      // Find any point on the minY plane that intersects the world
-      // First construct a perpendicular plane that will allow us to find a sample point.
-      // This plane is vertical and goes through the points (0,0,0) and (0,1,0)
-      // Then use it to compute a sample point.
-      final GeoPoint intPoint = yPlane.getSampleIntersectionPoint(planetModel, yVerticalPlane);
-      if (intPoint != null) {
-        yEdges = new GeoPoint[]{intPoint};
-      } else {
-        yEdges = EMPTY_POINTS;
-      }
-    } else {
-      yEdges = EMPTY_POINTS;
-    }
-
-    this.edgePoints = glueTogether(minXY, maxXY, YminZ, YmaxZ, yEdges);
-  }
-
-  @Override
-  protected GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-  
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return minXPlane.isWithin(x, y, z) &&
-      maxXPlane.isWithin(x, y, z) &&
-      yPlane.evaluateIsZero(x, y, z) &&
-      minZPlane.isWithin(x, y, z) &&
-      maxZPlane.isWithin(x, y, z);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    //System.err.println(this+" getrelationship with "+path);
-    final int insideRectangle = isShapeInsideArea(path);
-    if (insideRectangle == SOME_INSIDE) {
-      //System.err.println(" some inside");
-      return OVERLAPS;
-    }
-
-    // Figure out if the entire XYZArea is contained by the shape.
-    final int insideShape = isAreaInsideShape(path);
-    if (insideShape == SOME_INSIDE) {
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
-      //System.err.println(" inside of each other");
-      return OVERLAPS;
-    }
-
-    if (path.intersects(yPlane, notableYPoints, minXPlane, maxXPlane, minZPlane, maxZPlane)) {
-      //System.err.println(" edges intersect");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE) {
-      //System.err.println(" shape inside rectangle");
-      return WITHIN;
-    }
-
-    if (insideShape == ALL_INSIDE) {
-      //System.err.println(" shape contains rectangle");
-      return CONTAINS;
-    }
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof XdYZSolid))
-      return false;
-    XdYZSolid other = (XdYZSolid) o;
-    if (!super.equals(other)) {
-      return false;
-    }
-    return other.minXPlane.equals(minXPlane) &&
-      other.maxXPlane.equals(maxXPlane) &&
-      other.yPlane.equals(yPlane) &&
-      other.minZPlane.equals(minZPlane) &&
-      other.maxZPlane.equals(maxZPlane);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result  + minXPlane.hashCode();
-    result = 31 * result  + maxXPlane.hashCode();
-    result = 31 * result  + yPlane.hashCode();
-    result = 31 * result  + minZPlane.hashCode();
-    result = 31 * result  + maxZPlane.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "XdYZSolid: {planetmodel="+planetModel+", minXplane="+minXPlane+", maxXplane="+maxXPlane+", yplane="+yPlane+", minZplane="+minZPlane+", maxZplane="+maxZPlane+"}";
-  }
-  
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XdYdZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XdYdZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XdYdZSolid.java
deleted file mode 100644
index 562e5a6..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XdYdZSolid.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in Y and Z.
- * This figure, in fact, represents either zero, one, or two points, so the
- * actual data stored is minimal.
- *
- * @lucene.internal
- */
-public class XdYdZSolid extends BaseXYZSolid {
-
-  /** The points in this figure on the planet surface; also doubles for edge points */
-  protected final GeoPoint[] surfacePoints;
-  
-  /**
-   * Sole constructor
-   *
-   *@param planetModel is the planet model.
-   *@param minX is the minimum X value.
-   *@param maxX is the maximum X value.
-   *@param Y is the Y value.
-   *@param Z is the Z value.
-   */
-  public XdYdZSolid(final PlanetModel planetModel,
-    final double minX,
-    final double maxX,
-    final double Y,
-    final double Z) {
-    super(planetModel);
-    // Argument checking
-    if (maxX - minX < Vector.MINIMUM_RESOLUTION)
-      throw new IllegalArgumentException("X values in wrong order or identical");
-
-    // Build the planes and intersect them.
-    final Plane yPlane = new Plane(yUnitVector,-Y);
-    final Plane zPlane = new Plane(zUnitVector,-Z);
-    final SidedPlane minXPlane = new SidedPlane(maxX,0.0,0.0,xUnitVector,-minX);
-    final SidedPlane maxXPlane = new SidedPlane(minX,0.0,0.0,xUnitVector,-maxX);
-    surfacePoints = yPlane.findIntersections(planetModel,zPlane,minXPlane,maxXPlane);
-  }
-
-  @Override
-  protected GeoPoint[] getEdgePoints() {
-    return surfacePoints;
-  }
-  
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    for (final GeoPoint p : surfacePoints) {
-      if (p.isIdentical(x,y,z))
-        return true;
-    }
-    return false;
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    //System.err.println(this+" getrelationship with "+path);
-    final int insideRectangle = isShapeInsideArea(path);
-    if (insideRectangle == SOME_INSIDE) {
-      //System.err.println(" some inside");
-      return OVERLAPS;
-    }
-
-    // Figure out if the entire XYZArea is contained by the shape.
-    final int insideShape = isAreaInsideShape(path);
-    if (insideShape == SOME_INSIDE) {
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
-      //System.err.println(" inside of each other");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE) {
-      return WITHIN;
-    }
-    
-    if (insideShape == ALL_INSIDE) {
-      //System.err.println(" shape contains rectangle");
-      return CONTAINS;
-    }
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof XdYdZSolid))
-      return false;
-    XdYdZSolid other = (XdYdZSolid) o;
-    if (!super.equals(other) || surfacePoints.length != other.surfacePoints.length ) {
-      return false;
-    }
-    for (int i = 0; i < surfacePoints.length; i++) {
-      if (!surfacePoints[i].equals(other.surfacePoints[i]))
-        return false;
-    }
-    return true;
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    for (final GeoPoint p : surfacePoints) {
-      result = 31 * result  + p.hashCode();
-    }
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    final StringBuilder sb = new StringBuilder();
-    for (final GeoPoint p : surfacePoints) {
-      sb.append(" ").append(p).append(" ");
-    }
-    return "XdYdZSolid: {planetmodel="+planetModel+", "+sb.toString()+"}";
-  }
-  
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXYZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXYZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXYZSolid.java
deleted file mode 100644
index 5a2a006..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXYZSolid.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in X.
- *
- * @lucene.internal
- */
-public class dXYZSolid extends BaseXYZSolid {
-
-  /** X plane */
-  protected final Plane xPlane;
-  /** Min-Y plane */
-  protected final SidedPlane minYPlane;
-  /** Max-Y plane */
-  protected final SidedPlane maxYPlane;
-  /** Min-Z plane */
-  protected final SidedPlane minZPlane;
-  /** Max-Z plane */
-  protected final SidedPlane maxZPlane;
-  
-  /** These are the edge points of the shape, which are defined to be at least one point on
-   * each surface area boundary.  In the case of a solid, this includes points which represent
-   * the intersection of XYZ bounding planes and the planet, as well as points representing
-   * the intersection of single bounding planes with the planet itself.
-   */
-  protected final GeoPoint[] edgePoints;
-
-  /** Notable points for XPlane */
-  protected final GeoPoint[] notableXPoints;
-
-  /**
-   * Sole constructor
-   *
-   *@param planetModel is the planet model.
-   *@param X is the X value.
-   *@param minY is the minimum Y value.
-   *@param maxY is the maximum Y value.
-   *@param minZ is the minimum Z value.
-   *@param maxZ is the maximum Z value.
-   */
-  public dXYZSolid(final PlanetModel planetModel,
-    final double X,
-    final double minY,
-    final double maxY,
-    final double minZ,
-    final double maxZ) {
-    super(planetModel);
-    // Argument checking
-    if (maxY - minY < Vector.MINIMUM_RESOLUTION)
-      throw new IllegalArgumentException("Y values in wrong order or identical");
-    if (maxZ - minZ < Vector.MINIMUM_RESOLUTION)
-      throw new IllegalArgumentException("Z values in wrong order or identical");
-
-    final double worldMinX = planetModel.getMinimumXValue();
-    final double worldMaxX = planetModel.getMaximumXValue();
-    
-    // Construct the planes
-    xPlane = new Plane(xUnitVector,-X);
-    minYPlane = new SidedPlane(0.0,maxY,0.0,yUnitVector,-minY);
-    maxYPlane = new SidedPlane(0.0,minY,0.0,yUnitVector,-maxY);
-    minZPlane = new SidedPlane(0.0,0.0,maxZ,zUnitVector,-minZ);
-    maxZPlane = new SidedPlane(0.0,0.0,minZ,zUnitVector,-maxZ);
-      
-    // We need at least one point on the planet surface for each manifestation of the shape.
-    // There can be up to 2 (on opposite sides of the world).  But we have to go through
-    // 4 combinations of adjacent planes in order to find out if any have 2 intersection solution.
-    // Typically, this requires 4 square root operations. 
-    final GeoPoint[] XminY = xPlane.findIntersections(planetModel,minYPlane,maxYPlane,minZPlane,maxZPlane);
-    final GeoPoint[] XmaxY = xPlane.findIntersections(planetModel,maxYPlane,minYPlane,minZPlane,maxZPlane);
-    final GeoPoint[] XminZ = xPlane.findIntersections(planetModel,minZPlane,maxZPlane,minYPlane,maxYPlane);
-    final GeoPoint[] XmaxZ = xPlane.findIntersections(planetModel,maxZPlane,minZPlane,minYPlane,maxYPlane);
-
-    notableXPoints = glueTogether(XminY, XmaxY, XminZ, XmaxZ);
-
-    // Now, compute the edge points.
-    // This is the trickiest part of setting up an XYZSolid.  We've computed intersections already, so
-    // we'll start there.  We know that at most there will be two disconnected shapes on the planet surface.
-    // But there's also a case where exactly one plane slices through the world, and none of the bounding plane
-    // intersections do.  Thus, if we don't find any of the edge intersection cases, we have to look for that last case.
-      
-    // We need to look at single-plane/world intersections.
-    // We detect these by looking at the world model and noting its x, y, and z bounds.
-    // For the single-dimension degenerate case, there's really only one plane that can possibly intersect the world.
-    // The cases we are looking for are when the four corner points for any given
-    // plane are all outside of the world, AND that plane intersects the world.
-    // There are four corner points all told; we must evaluate these WRT the planet surface.
-    final boolean XminYminZ = planetModel.pointOutside(X, minY, minZ);
-    final boolean XminYmaxZ = planetModel.pointOutside(X, minY, maxZ);
-    final boolean XmaxYminZ = planetModel.pointOutside(X, maxY, minZ);
-    final boolean XmaxYmaxZ = planetModel.pointOutside(X, maxY, maxZ);
-
-    final GeoPoint[] xEdges;
-    if (X - worldMinX >= -Vector.MINIMUM_RESOLUTION && X - worldMaxX <= Vector.MINIMUM_RESOLUTION &&
-      minY < 0.0 && maxY > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
-      XminYminZ && XminYmaxZ && XmaxYminZ && XmaxYmaxZ) {
-      // Find any point on the X plane that intersects the world
-      // First construct a perpendicular plane that will allow us to find a sample point.
-      // This plane is vertical and goes through the points (0,0,0) and (1,0,0)
-      // Then use it to compute a sample point.
-      final GeoPoint intPoint = xPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
-      if (intPoint != null) {
-        xEdges = new GeoPoint[]{intPoint};
-      } else {
-        xEdges = EMPTY_POINTS;
-      }
-    } else {
-      xEdges = EMPTY_POINTS;
-    }
-
-    this.edgePoints = glueTogether(XminY,XmaxY,XminZ,XmaxZ,xEdges);
-  }
-
-  @Override
-  protected GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-  
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return xPlane.evaluateIsZero(x, y, z) &&
-      minYPlane.isWithin(x, y, z) &&
-      maxYPlane.isWithin(x, y, z) &&
-      minZPlane.isWithin(x, y, z) &&
-      maxZPlane.isWithin(x, y, z);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    //System.err.println(this+" getrelationship with "+path);
-    final int insideRectangle = isShapeInsideArea(path);
-    if (insideRectangle == SOME_INSIDE) {
-      //System.err.println(" some shape points inside area");
-      return OVERLAPS;
-    }
-
-    // Figure out if the entire XYZArea is contained by the shape.
-    final int insideShape = isAreaInsideShape(path);
-    if (insideShape == SOME_INSIDE) {
-      //System.err.println(" some area points inside shape");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
-      //System.err.println(" inside of each other");
-      return OVERLAPS;
-    }
-
-    // The entire locus of points in this shape is on a single plane, so we only need ot look for an intersection with that plane.
-    //System.err.println("xPlane = "+xPlane);
-    if (path.intersects(xPlane, notableXPoints, minYPlane, maxYPlane, minZPlane, maxZPlane)) {
-      //System.err.println(" edges intersect");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE) {
-      //System.err.println(" shape points inside area");
-      return WITHIN;
-    }
-
-    if (insideShape == ALL_INSIDE) {
-      //System.err.println(" shape contains all area");
-      return CONTAINS;
-    }
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof dXYZSolid))
-      return false;
-    dXYZSolid other = (dXYZSolid) o;
-    if (!super.equals(other)) {
-      return false;
-    }
-    return other.xPlane.equals(xPlane) &&
-      other.minYPlane.equals(minYPlane) &&
-      other.maxYPlane.equals(maxYPlane) &&
-      other.minZPlane.equals(minZPlane) &&
-      other.maxZPlane.equals(maxZPlane);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result  + xPlane.hashCode();
-    result = 31 * result  + minYPlane.hashCode();
-    result = 31 * result  + maxYPlane.hashCode();
-    result = 31 * result  + minZPlane.hashCode();
-    result = 31 * result  + maxZPlane.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "dXYZSolid: {planetmodel="+planetModel+", xplane="+xPlane+", minYplane="+minYPlane+", maxYplane="+maxYPlane+", minZplane="+minZPlane+", maxZplane="+maxZPlane+"}";
-  }
-  
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXYdZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXYdZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXYdZSolid.java
deleted file mode 100644
index 96b3004..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXYdZSolid.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in X and Z.
- * This figure, in fact, represents either zero, one, or two points, so the
- * actual data stored is minimal.
- *
- * @lucene.internal
- */
-public class dXYdZSolid extends BaseXYZSolid {
-
-  /** The points in this figure on the planet surface; also doubles for edge points */
-  protected final GeoPoint[] surfacePoints;
-  
-  /**
-   * Sole constructor
-   *
-   *@param planetModel is the planet model.
-   *@param X is the X value.
-   *@param minY is the minimum Y value.
-   *@param maxY is the maximum Y value.
-   *@param Z is the Z value.
-   */
-  public dXYdZSolid(final PlanetModel planetModel,
-    final double X,
-    final double minY,
-    final double maxY,
-    final double Z) {
-    super(planetModel);
-    // Argument checking
-    if (maxY - minY < Vector.MINIMUM_RESOLUTION)
-      throw new IllegalArgumentException("Y values in wrong order or identical");
-
-    // Build the planes and intersect them.
-    final Plane xPlane = new Plane(xUnitVector,-X);
-    final Plane zPlane = new Plane(zUnitVector,-Z);
-    final SidedPlane minYPlane = new SidedPlane(0.0,maxY,0.0,yUnitVector,-minY);
-    final SidedPlane maxYPlane = new SidedPlane(0.0,minY,0.0,yUnitVector,-maxY);
-    surfacePoints = xPlane.findIntersections(planetModel,zPlane,minYPlane,maxYPlane);
-  }
-
-  @Override
-  protected GeoPoint[] getEdgePoints() {
-    return surfacePoints;
-  }
-  
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    for (final GeoPoint p : surfacePoints) {
-      if (p.isIdentical(x,y,z))
-        return true;
-    }
-    return false;
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    //System.err.println(this+" getrelationship with "+path);
-    final int insideRectangle = isShapeInsideArea(path);
-    if (insideRectangle == SOME_INSIDE) {
-      //System.err.println(" some inside");
-      return OVERLAPS;
-    }
-
-    // Figure out if the entire XYZArea is contained by the shape.
-    final int insideShape = isAreaInsideShape(path);
-    if (insideShape == SOME_INSIDE) {
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
-      //System.err.println(" inside of each other");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE) {
-      return WITHIN;
-    }
-    
-    if (insideShape == ALL_INSIDE) {
-      //System.err.println(" shape contains rectangle");
-      return CONTAINS;
-    }
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof dXYdZSolid))
-      return false;
-    dXYdZSolid other = (dXYdZSolid) o;
-    if (!super.equals(other) || surfacePoints.length != other.surfacePoints.length ) {
-      return false;
-    }
-    for (int i = 0; i < surfacePoints.length; i++) {
-      if (!surfacePoints[i].equals(other.surfacePoints[i]))
-        return false;
-    }
-    return true;
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    for (final GeoPoint p : surfacePoints) {
-      result = 31 * result  + p.hashCode();
-    }
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    final StringBuilder sb = new StringBuilder();
-    for (final GeoPoint p : surfacePoints) {
-      sb.append(" ").append(p).append(" ");
-    }
-    return "dXYdZSolid: {planetmodel="+planetModel+", "+sb.toString()+"}";
-  }
-  
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXdYZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXdYZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXdYZSolid.java
deleted file mode 100644
index b58cd92..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXdYZSolid.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in X and Y.
- * This figure, in fact, represents either zero, one, or two points, so the
- * actual data stored is minimal.
- *
- * @lucene.internal
- */
-public class dXdYZSolid extends BaseXYZSolid {
-
-  /** The points in this figure on the planet surface; also doubles for edge points */
-  protected final GeoPoint[] surfacePoints;
-  
-  /**
-   * Sole constructor
-   *
-   *@param planetModel is the planet model.
-   *@param X is the X value.
-   *@param Y is the Y value.
-   *@param minZ is the minimum Z value.
-   *@param maxZ is the maximum Z value.
-   */
-  public dXdYZSolid(final PlanetModel planetModel,
-    final double X,
-    final double Y,
-    final double minZ,
-    final double maxZ) {
-    super(planetModel);
-    // Argument checking
-    if (maxZ - minZ < Vector.MINIMUM_RESOLUTION)
-      throw new IllegalArgumentException("Z values in wrong order or identical");
-
-    // Build the planes and intersect them.
-    final Plane xPlane = new Plane(xUnitVector,-X);
-    final Plane yPlane = new Plane(yUnitVector,-Y);
-    final SidedPlane minZPlane = new SidedPlane(0.0,0.0,maxZ,zUnitVector,-minZ);
-    final SidedPlane maxZPlane = new SidedPlane(0.0,0.0,minZ,zUnitVector,-maxZ);
-    surfacePoints = xPlane.findIntersections(planetModel,yPlane,minZPlane,maxZPlane);
-  }
-
-  @Override
-  protected GeoPoint[] getEdgePoints() {
-    return surfacePoints;
-  }
-  
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    for (final GeoPoint p : surfacePoints) {
-      if (p.isIdentical(x,y,z))
-        return true;
-    }
-    return false;
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    //System.err.println(this+" getrelationship with "+path);
-    final int insideRectangle = isShapeInsideArea(path);
-    if (insideRectangle == SOME_INSIDE) {
-      //System.err.println(" some inside");
-      return OVERLAPS;
-    }
-
-    // Figure out if the entire XYZArea is contained by the shape.
-    final int insideShape = isAreaInsideShape(path);
-    if (insideShape == SOME_INSIDE) {
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
-      //System.err.println(" inside of each other");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE) {
-      return WITHIN;
-    }
-    
-    if (insideShape == ALL_INSIDE) {
-      //System.err.println(" shape contains rectangle");
-      return CONTAINS;
-    }
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof dXdYZSolid))
-      return false;
-    dXdYZSolid other = (dXdYZSolid) o;
-    if (!super.equals(other) || surfacePoints.length != other.surfacePoints.length ) {
-      return false;
-    }
-    for (int i = 0; i < surfacePoints.length; i++) {
-      if (!surfacePoints[i].equals(other.surfacePoints[i]))
-        return false;
-    }
-    return true;
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    for (final GeoPoint p : surfacePoints) {
-      result = 31 * result  + p.hashCode();
-    }
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    final StringBuilder sb = new StringBuilder();
-    for (final GeoPoint p : surfacePoints) {
-      sb.append(" ").append(p).append(" ");
-    }
-    return "dXdYZSolid: {planetmodel="+planetModel+", "+sb.toString()+"}";
-  }
-  
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXdYdZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXdYdZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXdYdZSolid.java
deleted file mode 100644
index b26cf63..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXdYdZSolid.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in all dimensions
- *
- * @lucene.internal
- */
-public class dXdYdZSolid extends BaseXYZSolid {
-
-  /** On surface? */
-  protected final boolean isOnSurface;
-  /** The point */
-  protected final GeoPoint thePoint;
-  
-  /** These are the edge points of the shape, which are defined to be at least one point on
-   * each surface area boundary.  In the case of a solid, this includes points which represent
-   * the intersection of XYZ bounding planes and the planet, as well as points representing
-   * the intersection of single bounding planes with the planet itself.
-   */
-  protected final GeoPoint[] edgePoints;
-
-  /** Empty array of {@link GeoPoint}. */
-  protected static final GeoPoint[] nullPoints = new GeoPoint[0];
-  
-  /**
-   * Sole constructor
-   *
-   *@param planetModel is the planet model.
-   *@param X is the X value.
-   *@param Y is the Y value.
-   *@param Z is the Z value.
-   */
-  public dXdYdZSolid(final PlanetModel planetModel,
-    final double X,
-    final double Y,
-    final double Z) {
-    super(planetModel);
-    isOnSurface = planetModel.pointOnSurface(X,Y,Z);
-    if (isOnSurface) {
-      thePoint = new GeoPoint(X,Y,Z);
-      edgePoints = new GeoPoint[]{thePoint};
-    } else {
-      thePoint = null;
-      edgePoints = nullPoints;
-    }
-  }
-
-  @Override
-  protected GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-  
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    if (!isOnSurface) {
-      return false;
-    }
-    return thePoint.isIdentical(x,y,z);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    if (!isOnSurface) {
-      return DISJOINT;
-    }
-    
-    //System.err.println(this+" getrelationship with "+path);
-    final int insideRectangle = isShapeInsideArea(path);
-    if (insideRectangle == SOME_INSIDE) {
-      //System.err.println(" some shape points inside area");
-      return OVERLAPS;
-    }
-
-    // Figure out if the entire XYZArea is contained by the shape.
-    final int insideShape = isAreaInsideShape(path);
-    if (insideShape == SOME_INSIDE) {
-      //System.err.println(" some area points inside shape");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
-      //System.err.println(" inside of each other");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE) {
-      //System.err.println(" shape inside area entirely");
-      return WITHIN;
-    }
-
-    if (insideShape == ALL_INSIDE) {
-      //System.err.println(" shape contains area entirely");
-      return CONTAINS;
-    }
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof dXdYdZSolid))
-      return false;
-    dXdYdZSolid other = (dXdYdZSolid) o;
-    if (!super.equals(other) ||
-      other.isOnSurface != isOnSurface) {
-      return false;
-    }
-    if (isOnSurface) {
-      return other.thePoint.equals(thePoint);
-    }
-    return true;
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + (isOnSurface?1:0);
-    if (isOnSurface) {
-      result = 31 * result  + thePoint.hashCode();
-    }
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "dXdYdZSolid: {planetmodel="+planetModel+", isOnSurface="+isOnSurface+", thePoint="+thePoint+"}";
-  }
-  
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/package-info.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/package-info.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/package-info.java
deleted file mode 100644
index 2b6af74..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/package-info.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * Shapes implemented using 3D planar geometry.
- */
-package org.apache.lucene.geo3d;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPoint.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPoint.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPoint.java
new file mode 100644
index 0000000..cd2c79a
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPoint.java
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d;
+
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.spatial3d.geom.GeoPoint;
+import org.apache.lucene.spatial3d.geom.GeoShape;
+import org.apache.lucene.spatial3d.geom.PlanetModel;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.NumericUtils;
+
+/**
+ * Add this to a document to index lat/lon or x/y/z point, indexed as a 3D point.
+ * Multiple values are allowed: just add multiple Geo3DPoint to the document with the
+ * same field name.
+ * <p>
+ * This field defines static factory methods for creating a shape query:
+ * <ul>
+ *   <li>{@link #newShapeQuery newShapeQuery()} for matching all points inside a specified shape
+ * </ul>
+ *
+ *  @lucene.experimental */
+public final class Geo3DPoint extends Field {
+
+  /** Indexing {@link FieldType}. */
+  public static final FieldType TYPE = new FieldType();
+  static {
+    TYPE.setDimensions(3, Integer.BYTES);
+    TYPE.freeze();
+  }
+
+  /** 
+   * Creates a new Geo3DPoint field with the specified lat, lon (in radians).
+   *
+   * @throws IllegalArgumentException if the field name is null or lat or lon are out of bounds
+   */
+  public Geo3DPoint(String name, double lat, double lon) {
+    super(name, TYPE);
+    // Translate lat/lon to x,y,z:
+    final GeoPoint point = new GeoPoint(PlanetModel.WGS84, lat, lon);
+    fillFieldsData(point.x, point.y, point.z);
+  }
+
+  /** 
+   * Creates a new Geo3DPoint field with the specified x,y,z.
+   *
+   * @throws IllegalArgumentException if the field name is null or lat or lon are out of bounds
+   */
+  public Geo3DPoint(String name, double x, double y, double z) {
+    super(name, TYPE);
+    fillFieldsData(x, y, z);
+  }
+
+  private void fillFieldsData(double x, double y, double z) {
+    byte[] bytes = new byte[12];
+    encodeDimension(x, bytes, 0);
+    encodeDimension(y, bytes, Integer.BYTES);
+    encodeDimension(z, bytes, 2*Integer.BYTES);
+    fieldsData = new BytesRef(bytes);
+  }
+
+  // public helper methods (e.g. for queries)
+  
+  /** Encode single dimension */
+  public static void encodeDimension(double value, byte bytes[], int offset) {
+    NumericUtils.intToSortableBytes(Geo3DUtil.encodeValue(PlanetModel.WGS84.getMaximumMagnitude(), value), bytes, offset);
+  }
+  
+  /** Decode single dimension */
+  public static double decodeDimension(byte value[], int offset) {
+    return Geo3DUtil.decodeValueCenter(PlanetModel.WGS84.getMaximumMagnitude(), NumericUtils.sortableBytesToInt(value, offset));
+  }
+
+  /** Returns a query matching all points inside the provided shape.
+   * 
+   * @param field field name. must not be {@code null}.
+   * @param shape Which {@link GeoShape} to match
+   */
+  public static Query newShapeQuery(String field, GeoShape shape) {
+    return new PointInGeo3DShapeQuery(field, shape);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder result = new StringBuilder();
+    result.append(getClass().getSimpleName());
+    result.append(" <");
+    result.append(name);
+    result.append(':');
+
+    BytesRef bytes = (BytesRef) fieldsData;
+    result.append(" x=" + decodeDimension(bytes.bytes, bytes.offset));
+    result.append(" y=" + decodeDimension(bytes.bytes, bytes.offset + Integer.BYTES));
+    result.append(" z=" + decodeDimension(bytes.bytes, bytes.offset + 2*Integer.BYTES));
+    result.append('>');
+    return result.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DUtil.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DUtil.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DUtil.java
new file mode 100644
index 0000000..0a0bf30
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DUtil.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d;
+
+class Geo3DUtil {
+
+  /** Clips the incoming value to the allowed min/max range before encoding, instead of throwing an exception. */
+  public static int encodeValueLenient(double planetMax, double x) {
+    if (x > planetMax) {
+      x = planetMax;
+    } else if (x < -planetMax) {
+      x = -planetMax;
+    }
+    return encodeValue(planetMax, x);
+  }
+
+  public static int encodeValue(double planetMax, double x) {
+    if (x > planetMax) {
+      throw new IllegalArgumentException("value=" + x + " is out-of-bounds (greater than planetMax=" + planetMax + ")");
+    }
+    if (x < -planetMax) {
+      throw new IllegalArgumentException("value=" + x + " is out-of-bounds (less than than -planetMax=" + -planetMax + ")");
+    }
+    long y = Math.round (x * (Integer.MAX_VALUE / planetMax));
+    assert y >= Integer.MIN_VALUE;
+    assert y <= Integer.MAX_VALUE;
+
+    return (int) y;
+  }
+
+  /** Center decode */
+  public static double decodeValueCenter(double planetMax, int x) {
+    return x * (planetMax / Integer.MAX_VALUE);
+  }
+
+  /** More negative decode, at bottom of cell */
+  public static double decodeValueMin(double planetMax, int x) {
+    return (((double)x) - 0.5) * (planetMax / Integer.MAX_VALUE);
+  }
+  
+  /** More positive decode, at top of cell  */
+  public static double decodeValueMax(double planetMax, int x) {
+    return (((double)x) + 0.5) * (planetMax / Integer.MAX_VALUE);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/PointInGeo3DShapeQuery.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/PointInGeo3DShapeQuery.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/PointInGeo3DShapeQuery.java
new file mode 100644
index 0000000..9df8752
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/PointInGeo3DShapeQuery.java
@@ -0,0 +1,215 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d;
+
+import java.io.IOException;
+
+import org.apache.lucene.spatial3d.geom.BasePlanetObject;
+import org.apache.lucene.spatial3d.geom.GeoArea;
+import org.apache.lucene.spatial3d.geom.GeoAreaFactory;
+import org.apache.lucene.spatial3d.geom.GeoShape;
+import org.apache.lucene.spatial3d.geom.PlanetModel;
+import org.apache.lucene.index.PointValues.IntersectVisitor;
+import org.apache.lucene.index.PointValues;
+import org.apache.lucene.index.PointValues.Relation;
+import org.apache.lucene.index.LeafReader;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.search.ConstantScoreScorer;
+import org.apache.lucene.search.ConstantScoreWeight;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.Weight;
+import org.apache.lucene.util.DocIdSetBuilder;
+import org.apache.lucene.util.NumericUtils;
+
+/** Finds all previously indexed points that fall within the specified polygon.
+ *
+ * <p>The field must be indexed using {@link Geo3DPoint}.
+ *
+ * @lucene.experimental */
+
+class PointInGeo3DShapeQuery extends Query {
+  final String field;
+  final GeoShape shape;
+
+  /** The lats/lons must be clockwise or counter-clockwise. */
+  public PointInGeo3DShapeQuery(String field, GeoShape shape) {
+    this.field = field;
+    this.shape = shape;
+
+    if (shape instanceof BasePlanetObject) {
+      BasePlanetObject planetObject = (BasePlanetObject) shape;
+      if (planetObject.getPlanetModel().equals(PlanetModel.WGS84) == false) {
+        throw new IllegalArgumentException("this qurey requires PlanetModel.WGS84, but got: " + planetObject.getPlanetModel());
+      }
+    }
+  }
+
+  @Override
+  public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
+
+    // I don't use RandomAccessWeight here: it's no good to approximate with "match all docs"; this is an inverted structure and should be
+    // used in the first pass:
+
+    return new ConstantScoreWeight(this) {
+
+      @Override
+      public Scorer scorer(LeafReaderContext context) throws IOException {
+        LeafReader reader = context.reader();
+        PointValues values = reader.getPointValues();
+        if (values == null) {
+          return null;
+        }
+
+        /*
+        XYZBounds bounds = new XYZBounds();
+        shape.getBounds(bounds);
+
+        final double planetMax = planetModel.getMaximumMagnitude();
+        if (planetMax != treeDV.planetMax) {
+          throw new IllegalStateException(planetModel + " is not the same one used during indexing: planetMax=" + planetMax + " vs indexing planetMax=" + treeDV.planetMax);
+        }
+        */
+
+        /*
+        GeoArea xyzSolid = GeoAreaFactory.makeGeoArea(planetModel,
+                                                      bounds.getMinimumX(),
+                                                      bounds.getMaximumX(),
+                                                      bounds.getMinimumY(),
+                                                      bounds.getMaximumY(),
+                                                      bounds.getMinimumZ(),
+                                                      bounds.getMaximumZ());
+
+        assert xyzSolid.getRelationship(shape) == GeoArea.WITHIN || xyzSolid.getRelationship(shape) == GeoArea.OVERLAPS: "expected WITHIN (1) or OVERLAPS (2) but got " + xyzSolid.getRelationship(shape) + "; shape="+shape+"; XYZSolid="+xyzSolid;
+        */
+
+        double planetMax = PlanetModel.WGS84.getMaximumMagnitude();
+
+        DocIdSetBuilder result = new DocIdSetBuilder(reader.maxDoc());
+
+        values.intersect(field,
+                         new IntersectVisitor() {
+
+                           @Override
+                           public void visit(int docID) {
+                             result.add(docID);
+                           }
+
+                           @Override
+                           public void visit(int docID, byte[] packedValue) {
+                             assert packedValue.length == 12;
+                             double x = Geo3DPoint.decodeDimension(packedValue, 0);
+                             double y = Geo3DPoint.decodeDimension(packedValue, Integer.BYTES);
+                             double z = Geo3DPoint.decodeDimension(packedValue, 2 * Integer.BYTES);
+                             if (shape.isWithin(x, y, z)) {
+                               result.add(docID);
+                             }
+                           }
+
+                           @Override
+                           public Relation compare(byte[] minPackedValue, byte[] maxPackedValue) {
+                             // Because the dimensional format operates in quantized (64 bit -> 32 bit) space, and the cell bounds
+                             // here are inclusive, we need to extend the bounds to the largest un-quantized values that
+                             // could quantize into these bounds.  The encoding (Geo3DUtil.encodeValue) does
+                             // a Math.round from double to long, so e.g. 1.4 -> 1, and -1.4 -> -1:
+                             double xMin = Geo3DUtil.decodeValueMin(planetMax, NumericUtils.sortableBytesToInt(minPackedValue, 0));
+                             double xMax = Geo3DUtil.decodeValueMax(planetMax, NumericUtils.sortableBytesToInt(maxPackedValue, 0));
+                             double yMin = Geo3DUtil.decodeValueMin(planetMax, NumericUtils.sortableBytesToInt(minPackedValue, 1 * Integer.BYTES));
+                             double yMax = Geo3DUtil.decodeValueMax(planetMax, NumericUtils.sortableBytesToInt(maxPackedValue, 1 * Integer.BYTES));
+                             double zMin = Geo3DUtil.decodeValueMin(planetMax, NumericUtils.sortableBytesToInt(minPackedValue, 2 * Integer.BYTES));
+                             double zMax = Geo3DUtil.decodeValueMax(planetMax, NumericUtils.sortableBytesToInt(maxPackedValue, 2 * Integer.BYTES));
+
+                             //System.out.println("  compare: x=" + cellXMin + "-" + cellXMax + " y=" + cellYMin + "-" + cellYMax + " z=" + cellZMin + "-" + cellZMax);
+                             assert xMin <= xMax;
+                             assert yMin <= yMax;
+                             assert zMin <= zMax;
+
+                             GeoArea xyzSolid = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84, xMin, xMax, yMin, yMax, zMin, zMax);
+
+                             switch(xyzSolid.getRelationship(shape)) {
+                             case GeoArea.CONTAINS:
+                               // Shape fully contains the cell
+                               //System.out.println("    inside");
+                               return Relation.CELL_INSIDE_QUERY;
+                             case GeoArea.OVERLAPS:
+                               // They do overlap but neither contains the other:
+                               //System.out.println("    crosses1");
+                               return Relation.CELL_CROSSES_QUERY;
+                             case GeoArea.WITHIN:
+                               // Cell fully contains the shape:
+                               //System.out.println("    crosses2");
+                               // return Relation.SHAPE_INSIDE_CELL;
+                               return Relation.CELL_CROSSES_QUERY;
+                             case GeoArea.DISJOINT:
+                               // They do not overlap at all
+                               //System.out.println("    outside");
+                               return Relation.CELL_OUTSIDE_QUERY;
+                             default:
+                               assert false;
+                               return Relation.CELL_CROSSES_QUERY;
+                             }
+                           }
+                         });
+
+        return new ConstantScoreScorer(this, score(), result.build().iterator());
+      }
+    };
+  }
+
+  public String getField() {
+    return field;
+  }
+
+  public GeoShape getShape() {
+    return shape;
+  }
+
+  @Override
+  @SuppressWarnings({"unchecked","rawtypes"})
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    if (!super.equals(o)) return false;
+
+    PointInGeo3DShapeQuery that = (PointInGeo3DShapeQuery) o;
+
+    return shape.equals(that.shape);
+  }
+
+  @Override
+  public final int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + shape.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString(String field) {
+    final StringBuilder sb = new StringBuilder();
+    sb.append(getClass().getSimpleName());
+    sb.append(':');
+    if (this.field.equals(field) == false) {
+      sb.append(" field=");
+      sb.append(this.field);
+      sb.append(':');
+    }
+    sb.append(" Shape: ");
+    sb.append(shape);
+    return sb.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/ArcDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/ArcDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/ArcDistance.java
new file mode 100644
index 0000000..bb60be0
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/ArcDistance.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Arc distance computation style.
+ *
+ * @lucene.experimental
+ */
+public class ArcDistance implements DistanceStyle {
+  
+  /** An instance of the ArcDistance DistanceStyle. */
+  public final static ArcDistance INSTANCE = new ArcDistance();
+  
+  /** Constructor.
+   */
+  public ArcDistance() {
+  }
+  
+  @Override
+  public double computeDistance(final GeoPoint point1, final GeoPoint point2) {
+    return point1.arcDistance(point2);
+  }
+  
+  @Override
+  public double computeDistance(final GeoPoint point1, final double x2, final double y2, final double z2) {
+    return point1.arcDistance(x2,y2,z2);
+  }
+
+  @Override
+  public double computeDistance(final PlanetModel planetModel, final Plane plane, final GeoPoint point, final Membership... bounds) {
+    return plane.arcDistance(planetModel, point, bounds);
+  }
+  
+  @Override
+  public double computeDistance(final PlanetModel planetModel, final Plane plane, final double x, final double y, final double z, final Membership... bounds) {
+    return plane.arcDistance(planetModel, x,y,z, bounds);
+  }
+
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/BasePlanetObject.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/BasePlanetObject.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/BasePlanetObject.java
new file mode 100644
index 0000000..5cd5acc
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/BasePlanetObject.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * All Geo3D shapes can derive from this base class, which furnishes
+ * some common code
+ *
+ * @lucene.internal
+ */
+public abstract class BasePlanetObject {
+
+  /** This is the planet model embedded in all objects derived from this
+   * class. */
+  protected final PlanetModel planetModel;
+  
+  /** Constructor creating class instance given a planet model.
+   * @param planetModel is the planet model.
+   */
+  public BasePlanetObject(final PlanetModel planetModel) {
+    this.planetModel = planetModel;
+  }
+
+  /** Returns the {@link PlanetModel} provided when this shape was created. */
+  public PlanetModel getPlanetModel() {
+    return planetModel;
+  }
+  
+  @Override
+  public int hashCode() {
+    return planetModel.hashCode();
+  }
+  
+  @Override
+  public boolean equals(final Object o) {
+    if (!(o instanceof BasePlanetObject))
+      return false;
+    return planetModel.equals(((BasePlanetObject)o).planetModel);
+  }
+}
+
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/BaseXYZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/BaseXYZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/BaseXYZSolid.java
new file mode 100644
index 0000000..16b52cc
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/BaseXYZSolid.java
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Base class of a family of 3D rectangles, bounded on six sides by X,Y,Z limits
+ *
+ * @lucene.internal
+ */
+public abstract class BaseXYZSolid extends BasePlanetObject implements XYZSolid {
+
+  /** Unit vector in x */
+  protected static final Vector xUnitVector = new Vector(1.0, 0.0, 0.0);
+  /** Unit vector in y */
+  protected static final Vector yUnitVector = new Vector(0.0, 1.0, 0.0);
+  /** Unit vector in z */
+  protected static final Vector zUnitVector = new Vector(0.0, 0.0, 1.0);
+  
+  /** Vertical plane normal to x unit vector passing through origin */
+  protected static final Plane xVerticalPlane = new Plane(0.0, 1.0, 0.0, 0.0);
+  /** Vertical plane normal to y unit vector passing through origin */
+  protected static final Plane yVerticalPlane = new Plane(1.0, 0.0, 0.0, 0.0);
+
+  /** Empty point vector */
+  protected static final GeoPoint[] EMPTY_POINTS = new GeoPoint[0];
+  
+  /**
+   * Base solid constructor.
+   *@param planetModel is the planet model.
+   */
+  public BaseXYZSolid(final PlanetModel planetModel) {
+    super(planetModel);
+  }
+  
+  /** Construct a single array from a number of individual arrays.
+   * @param pointArrays is the array of point arrays.
+   * @return the single unified array.
+   */
+  protected static GeoPoint[] glueTogether(final GeoPoint[]... pointArrays) {
+    int count = 0;
+    for (final GeoPoint[] pointArray : pointArrays) {
+      count += pointArray.length;
+    }
+    final GeoPoint[] rval = new GeoPoint[count];
+    count = 0;
+    for (final GeoPoint[] pointArray : pointArrays) {
+      for (final GeoPoint point : pointArray) {
+        rval[count++] = point;
+      }
+    }
+    return rval;
+  }
+  
+  @Override
+  public boolean isWithin(final Vector point) {
+    return isWithin(point.x, point.y, point.z);
+  }
+  
+  @Override
+  public abstract boolean isWithin(final double x, final double y, final double z);
+  
+  // Signals for relationship of edge points to shape
+  
+  /** All edgepoints inside shape */
+  protected final static int ALL_INSIDE = 0;
+  /** Some edgepoints inside shape */
+  protected final static int SOME_INSIDE = 1;
+  /** No edgepoints inside shape */
+  protected final static int NONE_INSIDE = 2;
+  /** No edgepoints at all (means a shape that is the whole world) */
+  protected final static int NO_EDGEPOINTS = 3;
+
+  /** Determine the relationship between this area and the provided
+   * shape's edgepoints.
+   *@param path is the shape.
+   *@return the relationship.
+   */
+  protected int isShapeInsideArea(final GeoShape path) {
+    final GeoPoint[] pathPoints = path.getEdgePoints();
+    if (pathPoints.length == 0)
+      return NO_EDGEPOINTS;
+    boolean foundOutside = false;
+    boolean foundInside = false;
+    for (final GeoPoint p : pathPoints) {
+      if (isWithin(p)) {
+        foundInside = true;
+      } else {
+        foundOutside = true;
+      }
+      if (foundInside && foundOutside) {
+        return SOME_INSIDE;
+      }
+    }
+    if (!foundInside && !foundOutside)
+      return NONE_INSIDE;
+    if (foundInside && !foundOutside)
+      return ALL_INSIDE;
+    if (foundOutside && !foundInside)
+      return NONE_INSIDE;
+    return SOME_INSIDE;
+  }
+
+  /** Determine the relationship between a shape and this area's
+   * edgepoints.
+   *@param path is the shape.
+   *@return the relationship.
+   */
+  protected int isAreaInsideShape(final GeoShape path) {
+    final GeoPoint[] edgePoints = getEdgePoints();
+    if (edgePoints.length == 0) {
+      return NO_EDGEPOINTS;
+    }
+    boolean foundOutside = false;
+    boolean foundInside = false;
+    for (final GeoPoint p : edgePoints) {
+      if (path.isWithin(p)) {
+        foundInside = true;
+      } else {
+        foundOutside = true;
+      }
+      if (foundInside && foundOutside) {
+        return SOME_INSIDE;
+      }
+    }
+    if (!foundInside && !foundOutside)
+      return NONE_INSIDE;
+    if (foundInside && !foundOutside)
+      return ALL_INSIDE;
+    if (foundOutside && !foundInside)
+      return NONE_INSIDE;
+    return SOME_INSIDE;
+  }
+
+  /** Get the edge points for this shape.
+   *@return the edge points.
+   */
+  protected abstract GeoPoint[] getEdgePoints();
+  
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof BaseXYZSolid))
+      return false;
+    BaseXYZSolid other = (BaseXYZSolid) o;
+    return super.equals(other);
+  }
+
+  @Override
+  public int hashCode() {
+    return super.hashCode();
+  }
+
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Bounds.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Bounds.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Bounds.java
new file mode 100755
index 0000000..4f7c663
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Bounds.java
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * 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:
+ * (1) No longitude bound possible
+ * (2) No upper latitude bound possible
+ * (3) No lower latitude bound possible
+ * When any of these have been applied, further application of
+ * points cannot override that decision.
+ *
+ * @lucene.experimental
+ */
+public interface Bounds {
+
+  /** 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.
+   *@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 single point.
+   *@param point is the point.
+   *@return the updated Bounds object.
+   */
+  public Bounds addPoint(final GeoPoint point);
+
+  /** Add an X value.
+   *@param point is the point to take the x value from.
+   *@return the updated object.
+   */
+  public Bounds addXValue(final GeoPoint point);
+
+  /** Add a Y value.
+   *@param point is the point to take the y value from.
+   *@return the updated object.
+   */
+  public Bounds addYValue(final GeoPoint point);
+
+  /** Add a Z value.
+   *@param point is the point to take the z value from.
+   *@return the updated object.
+   */
+  public Bounds addZValue(final GeoPoint point);
+  
+  /** Signal that the shape exceeds Math.PI in longitude.
+   *@return the updated Bounds object.
+   */
+  public Bounds isWide();
+  
+  /** Signal that there is no longitude bound.
+   *@return the updated Bounds object.
+   */
+  public Bounds noLongitudeBound();
+
+  /** Signal that there is no top latitude bound.
+   *@return the updated Bounds object.
+   */
+  public Bounds noTopLatitudeBound();
+
+  /** Signal that there is no bottom latitude bound.
+   *@return the updated Bounds object.
+   */
+  public Bounds noBottomLatitudeBound();
+  
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/DistanceStyle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/DistanceStyle.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/DistanceStyle.java
new file mode 100644
index 0000000..8c8658d
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/DistanceStyle.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Distance computation styles, supporting various ways of computing
+ * distance to shapes.
+ *
+ * @lucene.experimental
+ */
+public interface DistanceStyle {
+
+  // convenient access to built-in styles:
+
+  /** Arc distance calculator */
+  public static final ArcDistance ARC = ArcDistance.INSTANCE;
+  /** Linear distance calculator */
+  public static final LinearDistance LINEAR = LinearDistance.INSTANCE;
+  /** Linear distance squared calculator */
+  public static final LinearSquaredDistance LINEAR_SQUARED = LinearSquaredDistance.INSTANCE;
+  /** Normal distance calculator */
+  public static final NormalDistance NORMAL = NormalDistance.INSTANCE;
+  /** Normal distance squared calculator */
+  public static final NormalSquaredDistance NORMAL_SQUARED = NormalSquaredDistance.INSTANCE;
+
+  /** Compute the distance from a point to another point.
+   * @param point1 Starting point
+   * @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);
+  }
+  
+  /** Compute the distance from a point to another point.
+   * @param point1 Starting point
+   * @param x2 Final point x
+   * @param y2 Final point y
+   * @param z2 Final point z
+   * @return the distance
+   */
+  public double computeDistance(final GeoPoint point1, final double x2, final double y2, final double z2);
+
+  /** Compute the distance from a plane to a point.
+   * @param planetModel The planet model
+   * @param plane The plane
+   * @param point The point
+   * @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);
+  }
+  
+  /** Compute the distance from a plane to a point.
+   * @param planetModel The planet model
+   * @param plane The plane
+   * @param x The point x
+   * @param y The point y
+   * @param z The point z
+   * @param bounds are the plane bounds
+   * @return the distance
+   */
+  public double computeDistance(final PlanetModel planetModel, final Plane plane, final double x, final double y, final double z, final Membership... bounds);
+
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoArea.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoArea.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoArea.java
new file mode 100755
index 0000000..5a6db0d
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoArea.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * A GeoArea represents a standard 2-D breakdown of a part of sphere.  It can
+ * be bounded in latitude, or bounded in both latitude and longitude, or not
+ * bounded at all.  The purpose of the interface is to describe bounding shapes used for
+ * computation of geo hashes.
+ *
+ * @lucene.experimental
+ */
+public interface GeoArea extends Membership {
+  // Since we don't know what each GeoArea's constraints are,
+  // we put the onus on the GeoArea implementation to do the right thing.
+  // This will, of course, rely heavily on methods provided by
+  // the underlying GeoShape class.
+
+  // Relationship values for "getRelationship()"
+  
+  /** The referenced shape CONTAINS this area */
+  public static final int CONTAINS = 0;
+  /** The referenced shape IS WITHIN this area */
+  public static final int WITHIN = 1;
+  /** The referenced shape OVERLAPS this area */
+  public static final int OVERLAPS = 2;
+  /** The referenced shape has no relation to this area */
+  public static final int DISJOINT = 3;
+
+  /**
+   * 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.
+   *
+   * It is permissible to return OVERLAPS instead of WITHIN if the shape
+   * intersects with the area at even a single point.  So, a circle inscribed in
+   * a rectangle could return either OVERLAPS or WITHIN, depending on
+   * implementation.  It is not permissible to return CONTAINS or DISJOINT
+   * in this circumstance, however.
+   *
+   * Similarly, it is permissible to return OVERLAPS instead of CONTAINS
+   * under conditions where the shape consists of multiple independent overlapping
+   * subshapes, and the area overlaps one of the subshapes.  It is not permissible
+   * to return WITHIN or DISJOINT in this circumstance, however.
+   *
+   * @param shape is the shape to consider.
+   * @return the relationship, from the perspective of the shape.
+   */
+  public int getRelationship(GeoShape shape);
+}
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoAreaFactory.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoAreaFactory.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoAreaFactory.java
new file mode 100755
index 0000000..0c3caa9
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoAreaFactory.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Factory for {@link GeoArea}.
+ *
+ * @lucene.experimental
+ */
+public class GeoAreaFactory {
+  private GeoAreaFactory() {
+  }
+
+  /**
+   * Create a GeoArea of the right kind given the specified bounds.
+   * @param planetModel is the planet model
+   * @param topLat    is the top latitude
+   * @param bottomLat is the bottom latitude
+   * @param leftLon   is the left longitude
+   * @param rightLon  is the right longitude
+   * @return a GeoArea corresponding to what was specified.
+   */
+  public static GeoArea makeGeoArea(final PlanetModel planetModel, final double topLat, final double bottomLat, final double leftLon, final double rightLon) {
+    return GeoBBoxFactory.makeGeoBBox(planetModel, topLat, bottomLat, leftLon, rightLon);
+  }
+
+  /**
+   * Create a GeoArea of the right kind given (x,y,z) bounds.
+   * @param planetModel is the planet model
+   * @param minX is the min X boundary
+   * @param maxX is the max X boundary
+   * @param minY is the min Y boundary
+   * @param maxY is the max Y boundary
+   * @param minZ is the min Z boundary
+   * @param maxZ is the max Z boundary
+   */
+  public static GeoArea makeGeoArea(final PlanetModel planetModel, final double minX, final double maxX, final double minY, final double maxY, final double minZ, final double maxZ) {
+    return XYZSolidFactory.makeXYZSolid(planetModel, minX, maxX, minY, maxY, minZ, maxZ);
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBBox.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBBox.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBBox.java
new file mode 100755
index 0000000..0ae2425
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBBox.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * All bounding box shapes have this interface in common.
+ * This describes methods that bounding boxes have above and beyond
+ * GeoMembershipShape's.
+ *
+ * @lucene.experimental
+ */
+public interface GeoBBox extends GeoMembershipShape, GeoSizeable, GeoArea {
+
+  /**
+   * Expand box by specified angle.
+   *
+   * @param angle is the angle amount to expand the GeoBBox by.
+   * @return a new GeoBBox.
+   */
+  public GeoBBox expand(double angle);
+
+}


[30/50] [abbrv] lucene-solr git commit: LUCENE-7075: convert test class to use points

Posted by no...@apache.org.
LUCENE-7075: convert test class to use points


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

Branch: refs/heads/apiv2
Commit: 862bf7b5ac340729869d8d0bec4c455142ad4b50
Parents: 5ea6ee7
Author: Robert Muir <rm...@apache.org>
Authored: Tue Mar 8 07:36:09 2016 -0500
Committer: Robert Muir <rm...@apache.org>
Committed: Tue Mar 8 07:36:34 2016 -0500

----------------------------------------------------------------------
 .../index/BaseStoredFieldsFormatTestCase.java   | 53 ++++++++------------
 1 file changed, 22 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/862bf7b5/lucene/test-framework/src/java/org/apache/lucene/index/BaseStoredFieldsFormatTestCase.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/index/BaseStoredFieldsFormatTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/index/BaseStoredFieldsFormatTestCase.java
index 840fdf5..c58d56a 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/index/BaseStoredFieldsFormatTestCase.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/index/BaseStoredFieldsFormatTestCase.java
@@ -33,20 +33,15 @@ import org.apache.lucene.codecs.Codec;
 import org.apache.lucene.codecs.StoredFieldsFormat;
 import org.apache.lucene.codecs.simpletext.SimpleTextCodec;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.LegacyDoubleField;
 import org.apache.lucene.document.Field.Store;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.FieldType.LegacyNumericType;
+import org.apache.lucene.document.IntPoint;
 import org.apache.lucene.document.FieldType;
-import org.apache.lucene.document.LegacyFloatField;
-import org.apache.lucene.document.LegacyIntField;
-import org.apache.lucene.document.LegacyLongField;
 import org.apache.lucene.document.NumericDocValuesField;
 import org.apache.lucene.document.StoredField;
 import org.apache.lucene.document.StringField;
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.LegacyNumericRangeQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.search.TopDocs;
@@ -244,51 +239,44 @@ public abstract class BaseStoredFieldsFormatTestCase extends BaseIndexFileFormat
     RandomIndexWriter w = new RandomIndexWriter(random(), dir);
     final int numDocs = atLeast(500);
     final Number[] answers = new Number[numDocs];
-    final LegacyNumericType[] typeAnswers = new LegacyNumericType[numDocs];
+    final Class<?>[] typeAnswers = new Class<?>[numDocs];
     for(int id=0;id<numDocs;id++) {
       Document doc = new Document();
       final Field nf;
-      final Field sf;
       final Number answer;
-      final LegacyNumericType typeAnswer;
+      final Class<?> typeAnswer;
       if (random().nextBoolean()) {
         // float/double
         if (random().nextBoolean()) {
           final float f = random().nextFloat();
           answer = Float.valueOf(f);
-          nf = new LegacyFloatField("nf", f, Field.Store.NO);
-          sf = new StoredField("nf", f);
-          typeAnswer = LegacyNumericType.FLOAT;
+          nf = new StoredField("nf", f);
+          typeAnswer = Float.class;
         } else {
           final double d = random().nextDouble();
           answer = Double.valueOf(d);
-          nf = new LegacyDoubleField("nf", d, Field.Store.NO);
-          sf = new StoredField("nf", d);
-          typeAnswer = LegacyNumericType.DOUBLE;
+          nf = new StoredField("nf", d);
+          typeAnswer = Double.class;
         }
       } else {
         // int/long
         if (random().nextBoolean()) {
           final int i = random().nextInt();
           answer = Integer.valueOf(i);
-          nf = new LegacyIntField("nf", i, Field.Store.NO);
-          sf = new StoredField("nf", i);
-          typeAnswer = LegacyNumericType.INT;
+          nf = new StoredField("nf", i);
+          typeAnswer = Integer.class;
         } else {
           final long l = random().nextLong();
           answer = Long.valueOf(l);
-          nf = new LegacyLongField("nf", l, Field.Store.NO);
-          sf = new StoredField("nf", l);
-          typeAnswer = LegacyNumericType.LONG;
+          nf = new StoredField("nf", l);
+          typeAnswer = Long.class;
         }
       }
       doc.add(nf);
-      doc.add(sf);
       answers[id] = answer;
       typeAnswers[id] = typeAnswer;
-      FieldType ft = new FieldType(LegacyIntField.TYPE_STORED);
-      ft.setNumericPrecisionStep(Integer.MAX_VALUE);
-      doc.add(new LegacyIntField("id", id, ft));
+      doc.add(new StoredField("id", id));
+      doc.add(new IntPoint("id", id));
       doc.add(new NumericDocValuesField("id", id));
       w.addDocument(doc);
     }
@@ -348,10 +336,10 @@ public abstract class BaseStoredFieldsFormatTestCase extends BaseIndexFileFormat
     List<Field> fields = Arrays.asList(
         new Field("bytes", bytes, ft),
         new Field("string", string, ft),
-        new LegacyLongField("long", l, Store.YES),
-        new LegacyIntField("int", i, Store.YES),
-        new LegacyFloatField("float", f, Store.YES),
-        new LegacyDoubleField("double", d, Store.YES)
+        new StoredField("long", l),
+        new StoredField("int", i),
+        new StoredField("float", f),
+        new StoredField("double", d)
     );
 
     for (int k = 0; k < 100; ++k) {
@@ -519,11 +507,14 @@ public abstract class BaseStoredFieldsFormatTestCase extends BaseIndexFileFormat
     final FieldType type = new FieldType(StringField.TYPE_STORED);
     type.setIndexOptions(IndexOptions.NONE);
     type.freeze();
-    LegacyIntField id = new LegacyIntField("id", 0, Store.YES);
+    IntPoint id = new IntPoint("id", 0);
+    StoredField idStored = new StoredField("id", 0);
     for (int i = 0; i < data.length; ++i) {
       Document doc = new Document();
       doc.add(id);
+      doc.add(idStored);
       id.setIntValue(i);
+      idStored.setIntValue(i);
       for (int j = 0; j < data[i].length; ++j) {
         Field f = new Field("bytes" + j, data[i][j], type);
         doc.add(f);
@@ -546,7 +537,7 @@ public abstract class BaseStoredFieldsFormatTestCase extends BaseIndexFileFormat
     for (int i = 0; i < 10; ++i) {
       final int min = random().nextInt(data.length);
       final int max = min + random().nextInt(20);
-      iw.deleteDocuments(LegacyNumericRangeQuery.newIntRange("id", min, max, true, false));
+      iw.deleteDocuments(IntPoint.newRangeQuery("id", min, max-1));
     }
 
     iw.forceMerge(2); // force merges with deletions


[50/50] [abbrv] lucene-solr git commit: Merge remote-tracking branch 'remotes/origin/master' into apiv2

Posted by no...@apache.org.
Merge remote-tracking branch 'remotes/origin/master' into apiv2


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

Branch: refs/heads/apiv2
Commit: ec4889a2b326df4ceb01ecb1ee096d550141fb8c
Parents: 7815408
Author: Noble Paul <no...@apache.org>
Authored: Wed Mar 9 21:26:24 2016 +0530
Committer: Noble Paul <no...@apache.org>
Committed: Wed Mar 9 21:26:24 2016 +0530

----------------------------------------------------------------------
 .../handler/admin/CollectionHandlerApi.java     |  4 +--
 .../solr/handler/admin/CollectionsHandler.java  | 26 +++++++++++++-------
 .../solr/handler/admin/TestCollectionAPIs.java  |  5 ++--
 3 files changed, 22 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ec4889a2/solr/core/src/java/org/apache/solr/handler/admin/CollectionHandlerApi.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CollectionHandlerApi.java b/solr/core/src/java/org/apache/solr/handler/admin/CollectionHandlerApi.java
index fb93d4f..78e5622 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/CollectionHandlerApi.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/CollectionHandlerApi.java
@@ -203,12 +203,12 @@ public class CollectionHandlerApi extends BaseHandlerApiSupport {
 
     @Override
     public void command(SolrQueryRequest req, SolrQueryResponse rsp, CommandOperation c, CollectionHandlerApi handler) throws Exception {
-      handler.handler.invokeAction(req,rsp,target);
+      handler.handler.invokeAction(req, rsp, handler.handler.coreContainer, target.action,target);
     }
 
     @Override
     public void GET(SolrQueryRequest req, SolrQueryResponse rsp, CollectionHandlerApi handler) throws Exception {
-      handler.handler.invokeAction(req, rsp, target);
+      handler.handler.invokeAction(req, rsp, handler.handler.coreContainer, target.action,target);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ec4889a2/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
index b12e1fb..c8d2c27 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
@@ -56,7 +56,6 @@ import static org.apache.solr.common.util.StrUtils.formatString;
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 
-import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -70,13 +69,13 @@ import java.util.concurrent.TimeUnit;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.StringUtils;
+import org.apache.solr.api.Api;
 import org.apache.solr.client.solrj.SolrResponse;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.CoreAdminRequest;
 import org.apache.solr.client.solrj.request.CoreAdminRequest.RequestSyncShard;
 import org.apache.solr.client.solrj.response.RequestStatusState;
 import org.apache.solr.client.solrj.util.SolrIdentifierValidator;
-import org.apache.solr.cloud.DistributedMap;
 import org.apache.solr.cloud.Overseer;
 import org.apache.solr.cloud.OverseerCollectionMessageHandler;
 import org.apache.solr.cloud.OverseerSolrResponse;
@@ -100,6 +99,7 @@ import org.apache.solr.common.cloud.ZkCoreNodeProps;
 import org.apache.solr.common.cloud.ZkNodeProps;
 import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.params.CollectionAdminParams;
+import org.apache.solr.common.params.CollectionParams;
 import org.apache.solr.common.params.CollectionParams.CollectionAction;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.CoreAdminParams;
@@ -111,7 +111,6 @@ import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.common.util.Utils;
 import org.apache.solr.core.CloudConfig;
 import org.apache.solr.core.CoreContainer;
-import org.apache.solr.handler.BlobHandler;
 import org.apache.solr.handler.RequestHandlerBase;
 import org.apache.solr.handler.component.ShardHandler;
 import org.apache.solr.request.SolrQueryRequest;
@@ -189,20 +188,21 @@ public class CollectionsHandler extends RequestHandlerBase {
         throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Unknown action: " + a);
       }
       CollectionOperation operation = CollectionOperation.get(action);
-      log.info("Invoked Collection Action :{} with params {} ", action.toLower(), req.getParamString());
-      invokeAction(req, rsp, operation);
+      log.info("Invoked Collection Action :{} with params {} and sendToOCPQueue={}", action.toLower(), req.getParamString(), operation.sendToOCPQueue);
+
+      invokeAction(req, rsp, cores, action, operation);
     } else {
       throw new SolrException(ErrorCode.BAD_REQUEST, "action is a required param");
     }
     rsp.setHttpCaching(false);
   }
 
-  void invokeAction(SolrQueryRequest req, SolrQueryResponse rsp, CollectionOperation operation) throws Exception {
+  void invokeAction(SolrQueryRequest req, SolrQueryResponse rsp, CoreContainer cores, CollectionAction action, CollectionOperation operation) throws Exception {
     if (!coreContainer.isZooKeeperAware()) {
       throw new SolrException(BAD_REQUEST,
           "Invalid request. collections can be accessed only in SolrCloud mode");
     }
-
+    SolrResponse response = null;
     Map<String, Object> props = operation.call(req, rsp, this);
     String asyncId = req.getParams().get(ASYNC);
     if (props != null) {
@@ -211,8 +211,16 @@ public class CollectionsHandler extends RequestHandlerBase {
       }
       props.put(QUEUE_OPERATION, operation.action.toLower());
       ZkNodeProps zkProps = new ZkNodeProps(props);
-      if (operation.sendToOCPQueue) handleResponse(operation.action.toLower(), zkProps, rsp, operation.timeOut);
-      else Overseer.getInQueue(coreContainer.getZkController().getZkClient()).offer(Utils.toJSON(props));
+      if (operation.sendToOCPQueue) {
+        response = handleResponse(operation.action.toLower(), zkProps, rsp, operation.timeOut);
+      }
+      else Overseer.getStateUpdateQueue(coreContainer.getZkController().getZkClient()).offer(Utils.toJSON(props));
+      final String collectionName = zkProps.getStr(NAME);
+      if (action.equals(CollectionAction.CREATE) && asyncId == null) {
+        if (rsp.getException() == null) {
+          waitForActiveCollection(collectionName, zkProps, cores, response);
+        }
+      }
     }
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ec4889a2/solr/core/src/test/org/apache/solr/handler/admin/TestCollectionAPIs.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/TestCollectionAPIs.java b/solr/core/src/test/org/apache/solr/handler/admin/TestCollectionAPIs.java
index 3d0c625..919e5b9 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/TestCollectionAPIs.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/TestCollectionAPIs.java
@@ -28,6 +28,7 @@ import java.util.Map;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.common.cloud.ZkNodeProps;
+import org.apache.solr.common.params.CollectionParams;
 import org.apache.solr.common.params.MapSolrParams;
 import org.apache.solr.common.util.Pair;
 import org.apache.solr.common.util.Utils;
@@ -99,7 +100,8 @@ public class TestCollectionAPIs extends SolrTestCaseJ4 {
     MockCollectionsHandler() { }
 
     @Override
-    protected void invokeAction(SolrQueryRequest req, SolrQueryResponse rsp, CollectionOperation operation) throws Exception {
+    void invokeAction(SolrQueryRequest req, SolrQueryResponse rsp, CoreContainer cores, CollectionParams.CollectionAction action,
+                      CollectionOperation operation) throws Exception {
       Map<String, Object> result = operation.call(req, rsp, this);
       if (result != null) {
         result.put(QUEUE_OPERATION, operation.action.toLower());
@@ -108,5 +110,4 @@ public class TestCollectionAPIs extends SolrTestCaseJ4 {
     }
   }
 
-
 }


[10/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXYdZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXYdZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXYdZSolid.java
new file mode 100644
index 0000000..d824f26
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXYdZSolid.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in X and Z.
+ * This figure, in fact, represents either zero, one, or two points, so the
+ * actual data stored is minimal.
+ *
+ * @lucene.internal
+ */
+public class dXYdZSolid extends BaseXYZSolid {
+
+  /** The points in this figure on the planet surface; also doubles for edge points */
+  protected final GeoPoint[] surfacePoints;
+  
+  /**
+   * Sole constructor
+   *
+   *@param planetModel is the planet model.
+   *@param X is the X value.
+   *@param minY is the minimum Y value.
+   *@param maxY is the maximum Y value.
+   *@param Z is the Z value.
+   */
+  public dXYdZSolid(final PlanetModel planetModel,
+    final double X,
+    final double minY,
+    final double maxY,
+    final double Z) {
+    super(planetModel);
+    // Argument checking
+    if (maxY - minY < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("Y values in wrong order or identical");
+
+    // Build the planes and intersect them.
+    final Plane xPlane = new Plane(xUnitVector,-X);
+    final Plane zPlane = new Plane(zUnitVector,-Z);
+    final SidedPlane minYPlane = new SidedPlane(0.0,maxY,0.0,yUnitVector,-minY);
+    final SidedPlane maxYPlane = new SidedPlane(0.0,minY,0.0,yUnitVector,-maxY);
+    surfacePoints = xPlane.findIntersections(planetModel,zPlane,minYPlane,maxYPlane);
+  }
+
+  @Override
+  protected GeoPoint[] getEdgePoints() {
+    return surfacePoints;
+  }
+  
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    for (final GeoPoint p : surfacePoints) {
+      if (p.isIdentical(x,y,z))
+        return true;
+    }
+    return false;
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    //System.err.println(this+" getrelationship with "+path);
+    final int insideRectangle = isShapeInsideArea(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some inside");
+      return OVERLAPS;
+    }
+
+    // Figure out if the entire XYZArea is contained by the shape.
+    final int insideShape = isAreaInsideShape(path);
+    if (insideShape == SOME_INSIDE) {
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
+      //System.err.println(" inside of each other");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      return WITHIN;
+    }
+    
+    if (insideShape == ALL_INSIDE) {
+      //System.err.println(" shape contains rectangle");
+      return CONTAINS;
+    }
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof dXYdZSolid))
+      return false;
+    dXYdZSolid other = (dXYdZSolid) o;
+    if (!super.equals(other) || surfacePoints.length != other.surfacePoints.length ) {
+      return false;
+    }
+    for (int i = 0; i < surfacePoints.length; i++) {
+      if (!surfacePoints[i].equals(other.surfacePoints[i]))
+        return false;
+    }
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    for (final GeoPoint p : surfacePoints) {
+      result = 31 * result  + p.hashCode();
+    }
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    final StringBuilder sb = new StringBuilder();
+    for (final GeoPoint p : surfacePoints) {
+      sb.append(" ").append(p).append(" ");
+    }
+    return "dXYdZSolid: {planetmodel="+planetModel+", "+sb.toString()+"}";
+  }
+  
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXdYZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXdYZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXdYZSolid.java
new file mode 100644
index 0000000..b9942b5
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXdYZSolid.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in X and Y.
+ * This figure, in fact, represents either zero, one, or two points, so the
+ * actual data stored is minimal.
+ *
+ * @lucene.internal
+ */
+public class dXdYZSolid extends BaseXYZSolid {
+
+  /** The points in this figure on the planet surface; also doubles for edge points */
+  protected final GeoPoint[] surfacePoints;
+  
+  /**
+   * Sole constructor
+   *
+   *@param planetModel is the planet model.
+   *@param X is the X value.
+   *@param Y is the Y value.
+   *@param minZ is the minimum Z value.
+   *@param maxZ is the maximum Z value.
+   */
+  public dXdYZSolid(final PlanetModel planetModel,
+    final double X,
+    final double Y,
+    final double minZ,
+    final double maxZ) {
+    super(planetModel);
+    // Argument checking
+    if (maxZ - minZ < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("Z values in wrong order or identical");
+
+    // Build the planes and intersect them.
+    final Plane xPlane = new Plane(xUnitVector,-X);
+    final Plane yPlane = new Plane(yUnitVector,-Y);
+    final SidedPlane minZPlane = new SidedPlane(0.0,0.0,maxZ,zUnitVector,-minZ);
+    final SidedPlane maxZPlane = new SidedPlane(0.0,0.0,minZ,zUnitVector,-maxZ);
+    surfacePoints = xPlane.findIntersections(planetModel,yPlane,minZPlane,maxZPlane);
+  }
+
+  @Override
+  protected GeoPoint[] getEdgePoints() {
+    return surfacePoints;
+  }
+  
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    for (final GeoPoint p : surfacePoints) {
+      if (p.isIdentical(x,y,z))
+        return true;
+    }
+    return false;
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    //System.err.println(this+" getrelationship with "+path);
+    final int insideRectangle = isShapeInsideArea(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some inside");
+      return OVERLAPS;
+    }
+
+    // Figure out if the entire XYZArea is contained by the shape.
+    final int insideShape = isAreaInsideShape(path);
+    if (insideShape == SOME_INSIDE) {
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
+      //System.err.println(" inside of each other");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      return WITHIN;
+    }
+    
+    if (insideShape == ALL_INSIDE) {
+      //System.err.println(" shape contains rectangle");
+      return CONTAINS;
+    }
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof dXdYZSolid))
+      return false;
+    dXdYZSolid other = (dXdYZSolid) o;
+    if (!super.equals(other) || surfacePoints.length != other.surfacePoints.length ) {
+      return false;
+    }
+    for (int i = 0; i < surfacePoints.length; i++) {
+      if (!surfacePoints[i].equals(other.surfacePoints[i]))
+        return false;
+    }
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    for (final GeoPoint p : surfacePoints) {
+      result = 31 * result  + p.hashCode();
+    }
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    final StringBuilder sb = new StringBuilder();
+    for (final GeoPoint p : surfacePoints) {
+      sb.append(" ").append(p).append(" ");
+    }
+    return "dXdYZSolid: {planetmodel="+planetModel+", "+sb.toString()+"}";
+  }
+  
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXdYdZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXdYdZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXdYdZSolid.java
new file mode 100644
index 0000000..66dcab8
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXdYdZSolid.java
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in all dimensions
+ *
+ * @lucene.internal
+ */
+public class dXdYdZSolid extends BaseXYZSolid {
+
+  /** On surface? */
+  protected final boolean isOnSurface;
+  /** The point */
+  protected final GeoPoint thePoint;
+  
+  /** These are the edge points of the shape, which are defined to be at least one point on
+   * each surface area boundary.  In the case of a solid, this includes points which represent
+   * the intersection of XYZ bounding planes and the planet, as well as points representing
+   * the intersection of single bounding planes with the planet itself.
+   */
+  protected final GeoPoint[] edgePoints;
+
+  /** Empty array of {@link GeoPoint}. */
+  protected static final GeoPoint[] nullPoints = new GeoPoint[0];
+  
+  /**
+   * Sole constructor
+   *
+   *@param planetModel is the planet model.
+   *@param X is the X value.
+   *@param Y is the Y value.
+   *@param Z is the Z value.
+   */
+  public dXdYdZSolid(final PlanetModel planetModel,
+    final double X,
+    final double Y,
+    final double Z) {
+    super(planetModel);
+    isOnSurface = planetModel.pointOnSurface(X,Y,Z);
+    if (isOnSurface) {
+      thePoint = new GeoPoint(X,Y,Z);
+      edgePoints = new GeoPoint[]{thePoint};
+    } else {
+      thePoint = null;
+      edgePoints = nullPoints;
+    }
+  }
+
+  @Override
+  protected GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+  
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    if (!isOnSurface) {
+      return false;
+    }
+    return thePoint.isIdentical(x,y,z);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    if (!isOnSurface) {
+      return DISJOINT;
+    }
+    
+    //System.err.println(this+" getrelationship with "+path);
+    final int insideRectangle = isShapeInsideArea(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some shape points inside area");
+      return OVERLAPS;
+    }
+
+    // Figure out if the entire XYZArea is contained by the shape.
+    final int insideShape = isAreaInsideShape(path);
+    if (insideShape == SOME_INSIDE) {
+      //System.err.println(" some area points inside shape");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
+      //System.err.println(" inside of each other");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      //System.err.println(" shape inside area entirely");
+      return WITHIN;
+    }
+
+    if (insideShape == ALL_INSIDE) {
+      //System.err.println(" shape contains area entirely");
+      return CONTAINS;
+    }
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof dXdYdZSolid))
+      return false;
+    dXdYdZSolid other = (dXdYdZSolid) o;
+    if (!super.equals(other) ||
+      other.isOnSurface != isOnSurface) {
+      return false;
+    }
+    if (isOnSurface) {
+      return other.thePoint.equals(thePoint);
+    }
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + (isOnSurface?1:0);
+    if (isOnSurface) {
+      result = 31 * result  + thePoint.hashCode();
+    }
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "dXdYdZSolid: {planetmodel="+planetModel+", isOnSurface="+isOnSurface+", thePoint="+thePoint+"}";
+  }
+  
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/package-info.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/package-info.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/package-info.java
new file mode 100644
index 0000000..446365c
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+/**
+ * Shapes implemented using 3D planar geometry.  This package has no dependencies aside from Java.
+ * This code was contributed under the name "Geo3D".
+ */
+package org.apache.lucene.spatial3d.geom;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/package-info.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/package-info.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/package-info.java
new file mode 100644
index 0000000..032d26f
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * Lucene field &amp; query support for the spatial geometry implemented in {@link org.apache.lucene.spatial3d.geom}.
+ */
+package org.apache.lucene.spatial3d;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/overview.html
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/overview.html b/lucene/spatial3d/src/java/overview.html
index 152d06e..293cc65a 100644
--- a/lucene/spatial3d/src/java/overview.html
+++ b/lucene/spatial3d/src/java/overview.html
@@ -23,7 +23,8 @@
   <h1>The Spatial3D Module for Apache Lucene</h1>
 
   <p>
-    APIs for planar spatial3d math.
+    APIs for planar spatial3d math.  It is mostly comprised of computational geometry code in the
+    "org.apache.lucene.spatial3d.geom" package (AKA "Geo3D").
   </p>
   </body>
 </html>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoBBoxTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoBBoxTest.java b/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoBBoxTest.java
deleted file mode 100755
index b76134e..0000000
--- a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoBBoxTest.java
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class GeoBBoxTest {
-
-  protected final double DEGREES_TO_RADIANS = Math.PI / 180.0;
-
-  @Test
-  public void testBBoxDegenerate() {
-    GeoBBox box;
-    GeoConvexPolygon cp;
-    int relationship;
-    List<GeoPoint> points = new ArrayList<GeoPoint>();
-    points.add(new GeoPoint(PlanetModel.SPHERE, 24 * DEGREES_TO_RADIANS, -30 * DEGREES_TO_RADIANS));
-    points.add(new GeoPoint(PlanetModel.SPHERE, -11 * DEGREES_TO_RADIANS, 101 * DEGREES_TO_RADIANS));
-    points.add(new GeoPoint(PlanetModel.SPHERE, -49 * DEGREES_TO_RADIANS, -176 * DEGREES_TO_RADIANS));
-    GeoMembershipShape shape = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points, 0);
-    box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, -64 * DEGREES_TO_RADIANS, -64 * DEGREES_TO_RADIANS, -180 * DEGREES_TO_RADIANS, 180 * DEGREES_TO_RADIANS);
-    relationship = box.getRelationship(shape);
-    assertEquals(GeoArea.CONTAINS, relationship);
-    box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, -61.85 * DEGREES_TO_RADIANS, -67.5 * DEGREES_TO_RADIANS, -180 * DEGREES_TO_RADIANS, -168.75 * DEGREES_TO_RADIANS);
-    //System.out.println("Shape = " + shape + " Rect = " + box);
-    relationship = box.getRelationship(shape);
-    assertEquals(GeoArea.CONTAINS, relationship);
-  }
-
-  @Test
-  public void testBBoxPointWithin() {
-    GeoBBox box;
-    GeoPoint gp;
-
-    // Standard normal Rect box, not crossing dateline
-    box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -1.0, 1.0);
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 0.0);
-    assertTrue(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.1, 0.0);
-    assertFalse(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0);
-    assertFalse(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 1.1);
-    assertFalse(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -1.1);
-    assertFalse(box.isWithin(gp));
-    assertEquals(0.1,box.computeOutsideDistance(DistanceStyle.ARC,gp),1e-2);
-    assertEquals(0.1,box.computeOutsideDistance(DistanceStyle.NORMAL,gp),1e-2);
-    assertEquals(0.1,box.computeOutsideDistance(DistanceStyle.NORMAL,gp),1e-2);
-
-    // Standard normal Rect box, crossing dateline
-    box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, Math.PI - 1.0, -Math.PI + 1.0);
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI);
-    assertTrue(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.1, -Math.PI);
-    assertFalse(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, -Math.PI);
-    assertFalse(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI + 1.1);
-    assertFalse(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, (-Math.PI - 1.1) + Math.PI * 2.0);
-    assertFalse(box.isWithin(gp));
-
-    // Latitude zone rectangle
-    box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -Math.PI, Math.PI);
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI);
-    assertTrue(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.1, -Math.PI);
-    assertFalse(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, -Math.PI);
-    assertFalse(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI + 1.1);
-    assertTrue(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, (-Math.PI - 1.1) + Math.PI * 2.0);
-    assertTrue(box.isWithin(gp));
-
-    // World
-    box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, Math.PI);
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI);
-    assertTrue(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.1, -Math.PI);
-    assertTrue(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, -Math.PI);
-    assertTrue(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI + 1.1);
-    assertTrue(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, (-Math.PI - 1.1) + Math.PI * 2.0);
-    assertTrue(box.isWithin(gp));
-
-  }
-
-  @Test
-  public void testBBoxExpand() {
-    GeoBBox box;
-    GeoPoint gp;
-    // Standard normal Rect box, not crossing dateline
-    box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -1.0, 1.0);
-    box = box.expand(0.1);
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.05, 0.0);
-    assertTrue(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.15, 0.0);
-    assertFalse(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.25 - 0.05, 0.0);
-    assertTrue(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.25 - 0.15, 0.0);
-    assertFalse(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -1.05);
-    assertTrue(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -1.15);
-    assertFalse(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 1.05);
-    assertTrue(box.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 1.15);
-    assertFalse(box.isWithin(gp));
-  }
-
-  @Test
-  public void testBBoxBounds() {
-    GeoBBox c;
-    LatLonBounds b;
-    XYZBounds xyzb;
-    GeoArea solid;
-    GeoPoint point;
-    int relationship;
-    
-    c= GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.7570958596622309, -0.7458670829264561, -0.9566079379002148, 1.4802570961901191);
-    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE,0.10922258701604912,0.1248184603754517,-0.8172414690802067,0.9959041483215542,-0.6136586624726926,0.6821740363641521);
-    point = new GeoPoint(PlanetModel.SPHERE, 0.3719987557178081, 1.4529582778845198);
-    assertTrue(c.isWithin(point));
-    assertTrue(solid.isWithin(point));
-    relationship = solid.getRelationship(c);
-    assertTrue(relationship == GeoArea.OVERLAPS || relationship == GeoArea.CONTAINS || relationship == GeoArea.WITHIN);
-
-    c= GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.006607096847842122, -0.002828135860810422, -0.0012934461873348349, 0.006727418645092394);
-    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE,0.9999995988328008,1.0000000002328306,-0.0012934708508166816,0.006727393021214471,-0.002828157275369464,0.006607074060760007);
-    point = new GeoPoint(PlanetModel.SPHERE, -5.236470872437899E-4, 3.992578692654256E-4);
-    assertTrue(c.isWithin(point));
-    assertTrue(solid.isWithin(point));
-    relationship = solid.getRelationship(c);
-    assertTrue(relationship == GeoArea.OVERLAPS || relationship == GeoArea.CONTAINS || relationship == GeoArea.WITHIN);
-    
-    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.25, -Math.PI * 0.25, -1.0, 1.0);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(-1.0, b.getLeftLongitude(), 0.000001);
-    assertEquals(1.0, b.getRightLongitude(), 0.000001);
-    assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
-    assertEquals(Math.PI * 0.25, b.getMaxLatitude(), 0.000001);
-    assertEquals(0.382051, xyzb.getMinimumX(), 0.000001);
-    assertEquals(1.0, xyzb.getMaximumX(), 0.000001);
-    assertEquals(-0.841471, xyzb.getMinimumY(), 0.000001);
-    assertEquals(0.841471, xyzb.getMaximumY(), 0.000001);
-    assertEquals(-0.707107, xyzb.getMinimumZ(), 0.000001);
-    assertEquals(0.707107, xyzb.getMaximumZ(), 0.000001);
-    
-    GeoArea area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE,
-      xyzb.getMinimumX() - 2.0 * Vector.MINIMUM_RESOLUTION,
-      xyzb.getMaximumX() + 2.0 * Vector.MINIMUM_RESOLUTION,
-      xyzb.getMinimumY() - 2.0 * Vector.MINIMUM_RESOLUTION,
-      xyzb.getMaximumY() + 2.0 * Vector.MINIMUM_RESOLUTION,
-      xyzb.getMinimumZ() - 2.0 * Vector.MINIMUM_RESOLUTION,
-      xyzb.getMaximumZ() + 2.0 * Vector.MINIMUM_RESOLUTION);
-    assertEquals(GeoArea.WITHIN, area.getRelationship(c));
-
-    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -1.0, 1.0);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(-1.0, b.getLeftLongitude(), 0.000001);
-    assertEquals(1.0, b.getRightLongitude(), 0.000001);
-    assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
-    assertEquals(0.0, b.getMaxLatitude(), 0.000001);
-    assertEquals(0.382051, xyzb.getMinimumX(), 0.000001);
-    assertEquals(1.0, xyzb.getMaximumX(), 0.000001);
-    assertEquals(-0.841471, xyzb.getMinimumY(), 0.000001);
-    assertEquals(0.841471, xyzb.getMaximumY(), 0.000001);
-    assertEquals(-0.707107, xyzb.getMinimumZ(), 0.000001);
-    assertEquals(0.0, xyzb.getMaximumZ(), 0.000001);
-
-    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, 1.0, -1.0);
-
-    b = new LatLonBounds();
-    c.getBounds(b);
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    assertTrue(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    //assertEquals(1.0,b.getLeftLongitude(),0.000001);
-    //assertEquals(-1.0,b.getRightLongitude(),0.000001);
-    assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
-    assertEquals(0.0, b.getMaxLatitude(), 0.000001);
-    assertEquals(-1.0, xyzb.getMinimumX(), 0.000001);
-    assertEquals(0.540303, xyzb.getMaximumX(), 0.000001);
-    assertEquals(-1.0, xyzb.getMinimumY(), 0.000001);
-    assertEquals(1.0, xyzb.getMaximumY(), 0.000001);
-    assertEquals(-0.707107, xyzb.getMinimumZ(), 0.000001);
-    assertEquals(0.0, xyzb.getMaximumZ(), 0.000001);
-
-
-    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -1.0, 1.0);
-
-    b = new LatLonBounds();
-    c.getBounds(b);
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    assertTrue(b.checkNoLongitudeBound());
-    assertTrue(b.checkNoTopLatitudeBound());
-    assertTrue(b.checkNoBottomLatitudeBound());
-    //assertEquals(-1.0, b.getLeftLongitude(), 0.000001);
-    //assertEquals(1.0, b.getRightLongitude(), 0.000001);
-    assertEquals(0.0, xyzb.getMinimumX(), 0.000001);
-    assertEquals(1.0, xyzb.getMaximumX(), 0.000001);
-    assertEquals(-0.841471, xyzb.getMinimumY(), 0.000001);
-    assertEquals(0.841471, xyzb.getMaximumY(), 0.000001);
-    assertEquals(-1.0, xyzb.getMinimumZ(), 0.000001);
-    assertEquals(1.0, xyzb.getMaximumZ(), 0.000001);
-
-    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, 1.0, -1.0);
-
-    b = new LatLonBounds();
-    c.getBounds(b);
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    assertTrue(b.checkNoLongitudeBound());
-    assertTrue(b.checkNoTopLatitudeBound());
-    assertTrue(b.checkNoBottomLatitudeBound());
-    //assertEquals(1.0,b.getLeftLongitude(),0.000001);
-    //assertEquals(-1.0,b.getRightLongitude(),0.000001);
-    assertEquals(-1.0, xyzb.getMinimumX(), 0.000001);
-    assertEquals(0.540303, xyzb.getMaximumX(), 0.000001);
-    assertEquals(-1.0, xyzb.getMinimumY(), 0.000001);
-    assertEquals(1.0, xyzb.getMaximumY(), 0.000001);
-    assertEquals(-1.0, xyzb.getMinimumZ(), 0.000001);
-    assertEquals(1.0, xyzb.getMaximumZ(), 0.000001);
-
-    // Check wide variants of rectangle and longitude slice
-
-    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -Math.PI + 0.1, Math.PI - 0.1);
-
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertTrue(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    //assertEquals(-Math.PI+0.1,b.getLeftLongitude(),0.000001);
-    //assertEquals(Math.PI-0.1,b.getRightLongitude(),0.000001);
-    assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
-    assertEquals(0.0, b.getMaxLatitude(), 0.000001);
-
-    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, Math.PI - 0.1, -Math.PI + 0.1);
-
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(Math.PI - 0.1, b.getLeftLongitude(), 0.000001);
-    assertEquals(-Math.PI + 0.1, b.getRightLongitude(), 0.000001);
-    assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
-    assertEquals(0.0, b.getMaxLatitude(), 0.000001);
-
-    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI + 0.1, Math.PI - 0.1);
-
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertTrue(b.checkNoLongitudeBound());
-    assertTrue(b.checkNoTopLatitudeBound());
-    assertTrue(b.checkNoBottomLatitudeBound());
-    //assertEquals(-Math.PI+0.1,b.getLeftLongitude(),0.000001);
-    //assertEquals(Math.PI-0.1,b.getRightLongitude(),0.000001);
-
-    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, Math.PI - 0.1, -Math.PI + 0.1);
-
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertTrue(b.checkNoLongitudeBound());
-    assertTrue(b.checkNoTopLatitudeBound());
-    assertTrue(b.checkNoBottomLatitudeBound());
-    //assertEquals(Math.PI - 0.1, b.getLeftLongitude(), 0.000001);
-    //assertEquals(-Math.PI + 0.1, b.getRightLongitude(), 0.000001);
-
-    // Check latitude zone
-    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 1.0, -1.0, -Math.PI, Math.PI);
-
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertTrue(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(-1.0, b.getMinLatitude(), 0.000001);
-    assertEquals(1.0, b.getMaxLatitude(), 0.000001);
-
-    // Now, combine a few things to test the bounds object
-    GeoBBox c1;
-    GeoBBox c2;
-
-    c1 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, 0.0);
-    c2 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI);
-
-    b = new LatLonBounds();
-    c1.getBounds(b);
-    c2.getBounds(b);
-    assertTrue(b.checkNoLongitudeBound());
-    assertTrue(b.checkNoTopLatitudeBound());
-    assertTrue(b.checkNoBottomLatitudeBound());
-
-    c1 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, 0.0);
-    c2 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI * 0.5);
-
-    b = new LatLonBounds();
-    c1.getBounds(b);
-    c2.getBounds(b);
-    assertTrue(b.checkNoLongitudeBound());
-    assertTrue(b.checkNoTopLatitudeBound());
-    assertTrue(b.checkNoBottomLatitudeBound());
-    //assertEquals(-Math.PI,b.getLeftLongitude(),0.000001);
-    //assertEquals(Math.PI*0.5,b.getRightLongitude(),0.000001);
-
-    c1 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI * 0.5, 0.0);
-    c2 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI);
-
-    b = new LatLonBounds();
-    c1.getBounds(b);
-    c2.getBounds(b);
-    assertTrue(b.checkNoLongitudeBound());
-    assertTrue(b.checkNoTopLatitudeBound());
-    assertTrue(b.checkNoBottomLatitudeBound());
-    //assertEquals(-Math.PI * 0.5,b.getLeftLongitude(),0.000001);
-    //assertEquals(Math.PI,b.getRightLongitude(),0.000001);
-
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoCircleTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoCircleTest.java b/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoCircleTest.java
deleted file mode 100755
index aa5c2e3..0000000
--- a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoCircleTest.java
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import org.apache.lucene.util.LuceneTestCase;
-
-public class GeoCircleTest extends LuceneTestCase {
-
-  @Test
-  public void testCircleDistance() {
-    GeoCircle c;
-    GeoPoint gp;
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.0, -0.5, 0.1);
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
-    assertEquals(Double.MAX_VALUE, c.computeDistance(DistanceStyle.ARC,gp), 0.0);
-    assertEquals(Double.MAX_VALUE, c.computeDistance(DistanceStyle.NORMAL,gp), 0.0);
-    assertEquals(Double.MAX_VALUE, c.computeDistance(DistanceStyle.NORMAL,gp), 0.0);
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
-    assertEquals(0.0, c.computeDistance(DistanceStyle.ARC,gp), 0.000001);
-    assertEquals(0.0, c.computeDistance(DistanceStyle.NORMAL,gp), 0.000001);
-    assertEquals(0.0, c.computeDistance(DistanceStyle.NORMAL,gp), 0.000001);
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.05, -0.5);
-    assertEquals(0.05, c.computeDistance(DistanceStyle.ARC,gp), 0.000001);
-    assertEquals(0.049995, c.computeDistance(DistanceStyle.LINEAR,gp), 0.000001);
-    assertEquals(0.049979, c.computeDistance(DistanceStyle.NORMAL,gp), 0.000001);
-  }
-
-  @Test
-  public void testCircleFullWorld() {
-    GeoCircle c;
-    GeoPoint gp;
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.0, -0.5, Math.PI);
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.0);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
-    assertTrue(c.isWithin(gp));
-    LatLonBounds b = new LatLonBounds();
-    c.getBounds(b);
-    assertTrue(b.checkNoLongitudeBound());
-    assertTrue(b.checkNoTopLatitudeBound());
-    assertTrue(b.checkNoBottomLatitudeBound());
-  }
-
-  @Test
-  public void testCirclePointWithin() {
-    GeoCircle c;
-    GeoPoint gp;
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.0, -0.5, 0.1);
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
-    assertFalse(c.isWithin(gp));
-    assertEquals(0.4,c.computeOutsideDistance(DistanceStyle.ARC,gp),1e-12);
-    assertEquals(0.12,c.computeOutsideDistance(DistanceStyle.NORMAL,gp),0.01);
-    assertEquals(0.4,c.computeOutsideDistance(DistanceStyle.LINEAR,gp),0.01);
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.0);
-    assertFalse(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
-    assertFalse(c.isWithin(gp));
-  }
-
-  @Test
-  public void testCircleBounds() {
-    GeoCircle c;
-    LatLonBounds b;
-    XYZBounds xyzb;
-    GeoArea area;
-    GeoPoint p1;
-    GeoPoint p2;
-    int relationship;
-
-    // ...
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84, -0.005931145568901605, -0.001942031539653079, 1.2991918568260272E-4);
-    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84, 1.001098377143621, 1.001100011578687, -0.00207467080358696, -0.0018136665346280983, -0.006067808248760161, -0.005807683665759485);
-    p1 = new GeoPoint(PlanetModel.WGS84, -0.00591253844632244, -0.0020069187259065093);
-    p2 = new GeoPoint(1.001099185736782, -0.0020091272069679327, -0.005919118245803968);
-    assertTrue(c.isWithin(p1));
-    assertTrue(area.isWithin(p1));
-    relationship = area.getRelationship(c);
-    assertTrue(relationship != GeoArea.DISJOINT);
-
-    // Twelfth BKD discovered failure
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84,-0.00824379317765984,-0.0011677469001838581,0.0011530035396910402);
-    p1 = new GeoPoint(PlanetModel.WGS84,-0.006505092992723671,0.007654282718327381);
-    p2 = new GeoPoint(1.0010681673665647,0.007662608264336381,-0.006512324005914593);
-    assertTrue(!c.isWithin(p1));
-    assertTrue(!c.isWithin(p2));
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84, 
-      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
-    relationship = area.getRelationship(c);
-    assertTrue(relationship == GeoArea.OVERLAPS || relationship == GeoArea.WITHIN);
-    // Point is actually outside the bounds, and outside the shape
-    assertTrue(!area.isWithin(p1));
-    // Approximate point the same
-    assertTrue(!area.isWithin(p2));
-    
-    // Eleventh BKD discovered failure
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE,-0.004431288600558495,-0.003687846671278374,1.704543429364245E-8);
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 
-      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
-    //System.err.println(area);
-    relationship = area.getRelationship(c);
-    assertTrue(GeoArea.WITHIN == relationship || GeoArea.OVERLAPS == relationship);
-
-    // Tenth BKD discovered failure
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84,-0.0018829770647349636,-0.001969499061382591,1.3045439293158305E-5);
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84, 
-      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
-    //System.err.println(area);
-    relationship = area.getRelationship(c);
-    assertTrue(GeoArea.WITHIN == relationship || GeoArea.OVERLAPS == relationship);
-
-    // Ninth BKD discovered failure
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE,-4.211990380885122E-5,-0.0022958453508173044,1.4318475623498535E-5);
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 
-      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
-    //System.err.println(area);
-    relationship = area.getRelationship(c);
-    assertTrue(GeoArea.WITHIN == relationship || GeoArea.OVERLAPS == relationship);
-    
-    // Eighth BKD discovered failure
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE,0.005321278689117842,-0.00216937368755372,1.5306034422500785E-4);
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 
-      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
-    //System.err.println(area);
-    relationship = area.getRelationship(c);
-    assertTrue(GeoArea.WITHIN == relationship || GeoArea.OVERLAPS == relationship);
-
-    // Seventh BKD discovered failure
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE,-0.0021627146783861745, -0.0017298167021592304,2.0818312293195752E-4);
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 
-      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
-    //System.err.println(area);
-    relationship = area.getRelationship(c);
-    assertTrue(GeoArea.WITHIN == relationship || GeoArea.OVERLAPS == relationship);
-
-    // Sixth BKD discovered failure
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84,-0.006450320645814321,0.004660694205115142,0.00489710732634323);
-    //xyzb = new XYZBounds();
-    //c.getBounds(xyzb);
-    //System.err.println("xmin="+xyzb.getMinimumX()+", xmax="+xyzb.getMaximumX()+",ymin="+xyzb.getMinimumY()+", ymax="+xyzb.getMaximumY()+",zmin="+xyzb.getMinimumZ()+", zmax="+xyzb.getMaximumZ());
-    //xmin=1.0010356621420726, xmax=1.0011141249179447,ymin=-2.5326643901354566E-4, ymax=0.009584741915757169,zmin=-0.011359874956269283, zmax=-0.0015549504447452225
-    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84,1.0010822580620098,1.0010945779732867,0.007079167343247293,0.007541006774427837,-0.0021855011220022575,-0.001896122718181518);
-    assertTrue(GeoArea.CONTAINS != area.getRelationship(c));
-    /*
-    p1 = new GeoPoint(1.0010893045436076,0.007380935180644008,-0.002140671370616495);
-    // This has a different bounding box, so we can't use it.
-    //p2 = new GeoPoint(PlanetModel.WGS84,-0.002164069780096702, 0.007505617500830066);
-    p2 = new GeoPoint(PlanetModel.WGS84,p1.getLatitude(),p1.getLongitude());
-    assertTrue(PlanetModel.WGS84.pointOnSurface(p2));
-    assertTrue(!c.isWithin(p2));
-    assertTrue(!area.isWithin(p2));
-    assertTrue(!c.isWithin(p1));
-    assertTrue(PlanetModel.WGS84.pointOnSurface(p1)); // This fails
-    assertTrue(!area.isWithin(p1)); // This fails
-    */
-    
-    // Fifth BKD discovered failure
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, -0.004282454525970269, -1.6739831367422277E-4, 1.959639723134033E-6);
-    assertTrue(c.isWithin(c.getEdgePoints()[0]));
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE,
-      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
-    assertTrue(GeoArea.WITHIN == area.getRelationship(c) || GeoArea.OVERLAPS == area.getRelationship(c));
-    
-    // Fourth BKD discovered failure
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, -0.0048795517261255, 0.004053904306995974, 5.93699764258874E-6);
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE,
-      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
-    assertTrue(GeoArea.WITHIN == area.getRelationship(c) || GeoArea.OVERLAPS == area.getRelationship(c));
-    
-    // Yet another test case from BKD
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84, 0.006229478708446979, 0.005570196723795424, 3.840276763694387E-5);
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84,
-      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
-    p1 = new GeoPoint(PlanetModel.WGS84, 0.006224927111830945, 0.005597367237251763);
-    p2 = new GeoPoint(1.0010836083810235, 0.005603490759433942, 0.006231850560862502);
-    assertTrue(PlanetModel.WGS84.pointOnSurface(p1));
-    //assertTrue(PlanetModel.WGS84.pointOnSurface(p2));
-    assertTrue(c.isWithin(p1));
-    assertTrue(c.isWithin(p2));
-    assertTrue(area.isWithin(p1));
-    assertTrue(area.isWithin(p2));
-    
-    // Another test case from BKD
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, -0.005955031040627789, -0.0029274772647399153, 1.601488279374338E-5);
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE,
-      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
-    
-    relationship = area.getRelationship(c);
-    assertTrue(relationship == GeoArea.WITHIN || relationship == GeoArea.OVERLAPS);
-    
-    // Test case from BKD
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, -0.765816119338, 0.991848766844, 0.8153163226330487);
-    p1 = new GeoPoint(0.7692262265236023, -0.055089298115534646, -0.6365973465711254);
-    assertTrue(c.isWithin(p1));
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    assertTrue(p1.x >= xyzb.getMinimumX() && p1.x <= xyzb.getMaximumX());
-    assertTrue(p1.y >= xyzb.getMinimumY() && p1.y <= xyzb.getMaximumY());
-    assertTrue(p1.z >= xyzb.getMinimumZ() && p1.z <= xyzb.getMaximumZ());
-    
-    // Vertical circle cases
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.0, -0.5, 0.1);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(-0.6, b.getLeftLongitude(), 0.000001);
-    assertEquals(-0.4, b.getRightLongitude(), 0.000001);
-    assertEquals(-0.1, b.getMinLatitude(), 0.000001);
-    assertEquals(0.1, b.getMaxLatitude(), 0.000001);
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.0, 0.5, 0.1);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(0.4, b.getLeftLongitude(), 0.000001);
-    assertEquals(0.6, b.getRightLongitude(), 0.000001);
-    assertEquals(-0.1, b.getMinLatitude(), 0.000001);
-    assertEquals(0.1, b.getMaxLatitude(), 0.000001);
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(-0.1, b.getLeftLongitude(), 0.000001);
-    assertEquals(0.1, b.getRightLongitude(), 0.000001);
-    assertEquals(-0.1, b.getMinLatitude(), 0.000001);
-    assertEquals(0.1, b.getMaxLatitude(), 0.000001);
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.0, Math.PI, 0.1);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(Math.PI - 0.1, b.getLeftLongitude(), 0.000001);
-    assertEquals(-Math.PI + 0.1, b.getRightLongitude(), 0.000001);
-    assertEquals(-0.1, b.getMinLatitude(), 0.000001);
-    assertEquals(0.1, b.getMaxLatitude(), 0.000001);
-    // Horizontal circle cases
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, Math.PI * 0.5, 0.0, 0.1);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertTrue(b.checkNoLongitudeBound());
-    assertTrue(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(Math.PI * 0.5 - 0.1, b.getMinLatitude(), 0.000001);
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0, 0.1);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertTrue(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertTrue(b.checkNoBottomLatitudeBound());
-    assertEquals(-Math.PI * 0.5 + 0.1, b.getMaxLatitude(), 0.000001);
-
-    // Now do a somewhat tilted plane, facing different directions.
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.01, 0.0, 0.1);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(0.11, b.getMaxLatitude(), 0.000001);
-    assertEquals(-0.09, b.getMinLatitude(), 0.000001);
-    assertEquals(-0.1, b.getLeftLongitude(), 0.00001);
-    assertEquals(0.1, b.getRightLongitude(), 0.00001);
-
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.01, Math.PI, 0.1);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(0.11, b.getMaxLatitude(), 0.000001);
-    assertEquals(-0.09, b.getMinLatitude(), 0.000001);
-    assertEquals(Math.PI - 0.1, b.getLeftLongitude(), 0.00001);
-    assertEquals(-Math.PI + 0.1, b.getRightLongitude(), 0.00001);
-
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.01, Math.PI * 0.5, 0.1);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(0.11, b.getMaxLatitude(), 0.000001);
-    assertEquals(-0.09, b.getMinLatitude(), 0.000001);
-    assertEquals(Math.PI * 0.5 - 0.1, b.getLeftLongitude(), 0.00001);
-    assertEquals(Math.PI * 0.5 + 0.1, b.getRightLongitude(), 0.00001);
-
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.01, -Math.PI * 0.5, 0.1);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(0.11, b.getMaxLatitude(), 0.000001);
-    assertEquals(-0.09, b.getMinLatitude(), 0.000001);
-    assertEquals(-Math.PI * 0.5 - 0.1, b.getLeftLongitude(), 0.00001);
-    assertEquals(-Math.PI * 0.5 + 0.1, b.getRightLongitude(), 0.00001);
-
-    // Slightly tilted, PI/4 direction.
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.01, Math.PI * 0.25, 0.1);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(0.11, b.getMaxLatitude(), 0.000001);
-    assertEquals(-0.09, b.getMinLatitude(), 0.000001);
-    assertEquals(Math.PI * 0.25 - 0.1, b.getLeftLongitude(), 0.00001);
-    assertEquals(Math.PI * 0.25 + 0.1, b.getRightLongitude(), 0.00001);
-
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.01, -Math.PI * 0.25, 0.1);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(0.11, b.getMaxLatitude(), 0.000001);
-    assertEquals(-0.09, b.getMinLatitude(), 0.000001);
-    assertEquals(-Math.PI * 0.25 - 0.1, b.getLeftLongitude(), 0.00001);
-    assertEquals(-Math.PI * 0.25 + 0.1, b.getRightLongitude(), 0.00001);
-
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, -0.01, Math.PI * 0.25, 0.1);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(0.09, b.getMaxLatitude(), 0.000001);
-    assertEquals(-0.11, b.getMinLatitude(), 0.000001);
-    assertEquals(Math.PI * 0.25 - 0.1, b.getLeftLongitude(), 0.00001);
-    assertEquals(Math.PI * 0.25 + 0.1, b.getRightLongitude(), 0.00001);
-
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, -0.01, -Math.PI * 0.25, 0.1);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(0.09, b.getMaxLatitude(), 0.000001);
-    assertEquals(-0.11, b.getMinLatitude(), 0.000001);
-    assertEquals(-Math.PI * 0.25 - 0.1, b.getLeftLongitude(), 0.00001);
-    assertEquals(-Math.PI * 0.25 + 0.1, b.getRightLongitude(), 0.00001);
-
-    // Now do a somewhat tilted plane.
-    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.01, -0.5, 0.1);
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(0.11, b.getMaxLatitude(), 0.000001);
-    assertEquals(-0.09, b.getMinLatitude(), 0.000001);
-    assertEquals(-0.6, b.getLeftLongitude(), 0.00001);
-    assertEquals(-0.4, b.getRightLongitude(), 0.00001);
-
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoConvexPolygonTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoConvexPolygonTest.java b/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoConvexPolygonTest.java
deleted file mode 100755
index d6ca7ba..0000000
--- a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoConvexPolygonTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class GeoConvexPolygonTest {
-
-
-  @Test
-  public void testPolygonPointWithin() {
-    GeoConvexPolygon c;
-    GeoPoint gp;
-    c = new GeoConvexPolygon(PlanetModel.SPHERE, -0.1, -0.5);
-    c.addPoint(0.0, -0.6, false);
-    c.addPoint(0.1, -0.5, false);
-    c.addPoint(0.0, -0.4, false);
-    c.done(false);
-    // Sample some points within
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.05, -0.5);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.05, -0.5);
-    assertTrue(c.isWithin(gp));
-    // Sample some nearby points outside, and compute distance-to-shape for them as well
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.65);
-    assertFalse(c.isWithin(gp));
-    assertEquals(0.05,c.computeOutsideDistance(DistanceStyle.ARC,gp),1e-12);
-    assertEquals(0.05,c.computeOutsideDistance(DistanceStyle.NORMAL,gp),1e-3);
-    assertEquals(0.05,c.computeOutsideDistance(DistanceStyle.LINEAR,gp),1e-3);
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.35);
-    assertFalse(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.15, -0.5);
-    assertFalse(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.15, -0.5);
-    assertFalse(c.isWithin(gp));
-    // Random points outside
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
-    assertFalse(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.0);
-    assertFalse(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
-    assertFalse(c.isWithin(gp));
-  }
-
-  @Test
-  public void testPolygonBounds() {
-    GeoConvexPolygon c;
-    LatLonBounds b;
-
-    c = new GeoConvexPolygon(PlanetModel.SPHERE, -0.1, -0.5);
-    c.addPoint(0.0, -0.6, false);
-    c.addPoint(0.1, -0.5, false);
-    c.addPoint(0.0, -0.4, false);
-    c.done(false);
-
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(-0.6, b.getLeftLongitude(), 0.000001);
-    assertEquals(-0.4, b.getRightLongitude(), 0.000001);
-    assertEquals(-0.1, b.getMinLatitude(), 0.000001);
-    assertEquals(0.1, b.getMaxLatitude(), 0.000001);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoModelTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoModelTest.java b/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoModelTest.java
deleted file mode 100644
index b3001d4..0000000
--- a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoModelTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Test basic plane functionality.
- */
-public class GeoModelTest {
-
-  protected final static PlanetModel scaledModel = new PlanetModel(1.2,1.5);
-  
-  @Test
-  public void testBasicCircle() {
-    // The point of this test is just to make sure nothing blows up doing normal things with a quite non-spherical model
-    // Make sure that the north pole is in the circle, and south pole isn't
-    final GeoPoint northPole = new GeoPoint(scaledModel, Math.PI * 0.5, 0.0);
-    final GeoPoint southPole = new GeoPoint(scaledModel, -Math.PI * 0.5, 0.0);
-    final GeoPoint point1 = new GeoPoint(scaledModel, Math.PI * 0.25, 0.0);
-    final GeoPoint point2 = new GeoPoint(scaledModel, Math.PI * 0.125, 0.0);
-    
-    GeoCircle circle = new GeoStandardCircle(scaledModel, Math.PI * 0.5, 0.0, 0.01);
-    assertTrue(circle.isWithin(northPole));
-    assertFalse(circle.isWithin(southPole));
-    assertFalse(circle.isWithin(point1));
-    LatLonBounds bounds;
-    bounds = new LatLonBounds();
-    circle.getBounds(bounds);
-    assertTrue(bounds.checkNoLongitudeBound());
-    assertTrue(bounds.checkNoTopLatitudeBound());
-    assertFalse(bounds.checkNoBottomLatitudeBound());
-    assertEquals(Math.PI * 0.5 - 0.01, bounds.getMinLatitude(), 0.01);
-
-    circle = new GeoStandardCircle(scaledModel, Math.PI * 0.25, 0.0, 0.01);
-    assertTrue(circle.isWithin(point1));
-    assertFalse(circle.isWithin(northPole));
-    assertFalse(circle.isWithin(southPole));
-    bounds = new LatLonBounds();
-    circle.getBounds(bounds);
-    assertFalse(bounds.checkNoTopLatitudeBound());
-    assertFalse(bounds.checkNoLongitudeBound());
-    assertFalse(bounds.checkNoBottomLatitudeBound());
-    assertEquals(Math.PI * 0.25 + 0.01, bounds.getMaxLatitude(), 0.00001);
-    assertEquals(Math.PI * 0.25 - 0.01, bounds.getMinLatitude(), 0.00001);
-    assertEquals(-0.0125, bounds.getLeftLongitude(), 0.0001);
-    assertEquals(0.0125, bounds.getRightLongitude(), 0.0001);
-
-    circle = new GeoStandardCircle(scaledModel, Math.PI * 0.125, 0.0, 0.01);
-    assertTrue(circle.isWithin(point2));
-    assertFalse(circle.isWithin(northPole));
-    assertFalse(circle.isWithin(southPole));
-    bounds = new LatLonBounds();
-    circle.getBounds(bounds);
-    assertFalse(bounds.checkNoLongitudeBound());
-    assertFalse(bounds.checkNoTopLatitudeBound());
-    assertFalse(bounds.checkNoBottomLatitudeBound());
-    // Symmetric, as expected
-    assertEquals(Math.PI * 0.125 - 0.01, bounds.getMinLatitude(), 0.00001);
-    assertEquals(Math.PI * 0.125 + 0.01, bounds.getMaxLatitude(), 0.00001);
-    assertEquals(-0.0089, bounds.getLeftLongitude(), 0.0001);
-    assertEquals(0.0089, bounds.getRightLongitude(), 0.0001);
-
-  }
-
-  @Test
-  public void testBasicRectangle() {
-    final GeoBBox bbox = GeoBBoxFactory.makeGeoBBox(scaledModel, 1.0, 0.0, 0.0, 1.0);
-    final GeoPoint insidePoint = new GeoPoint(scaledModel, 0.5, 0.5);
-    assertTrue(bbox.isWithin(insidePoint));
-    final GeoPoint topOutsidePoint = new GeoPoint(scaledModel, 1.01, 0.5);
-    assertFalse(bbox.isWithin(topOutsidePoint));
-    final GeoPoint bottomOutsidePoint = new GeoPoint(scaledModel, -0.01, 0.5);
-    assertFalse(bbox.isWithin(bottomOutsidePoint));
-    final GeoPoint leftOutsidePoint = new GeoPoint(scaledModel, 0.5, -0.01);
-    assertFalse(bbox.isWithin(leftOutsidePoint));
-    final GeoPoint rightOutsidePoint = new GeoPoint(scaledModel, 0.5, 1.01);
-    assertFalse(bbox.isWithin(rightOutsidePoint));
-    final LatLonBounds bounds = new LatLonBounds();
-    bbox.getBounds(bounds);
-    assertFalse(bounds.checkNoLongitudeBound());
-    assertFalse(bounds.checkNoTopLatitudeBound());
-    assertFalse(bounds.checkNoBottomLatitudeBound());
-    assertEquals(1.0, bounds.getMaxLatitude(), 0.00001);
-    assertEquals(0.0, bounds.getMinLatitude(), 0.00001);
-    assertEquals(1.0, bounds.getRightLongitude(), 0.00001);
-    assertEquals(0.0, bounds.getLeftLongitude(), 0.00001);
-  }
-  
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoPathTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoPathTest.java b/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoPathTest.java
deleted file mode 100755
index fea7ed4..0000000
--- a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoPathTest.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-import org.junit.Test;
-
-import static java.lang.Math.toRadians;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class GeoPathTest {
-
-  @Test
-  public void testPathDistance() {
-    // Start with a really simple case
-    GeoPath p;
-    GeoPoint gp;
-    p = new GeoPath(PlanetModel.SPHERE, 0.1);
-    p.addPoint(0.0, 0.0);
-    p.addPoint(0.0, 0.1);
-    p.addPoint(0.0, 0.2);
-    p.done();
-    gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.15);
-    assertEquals(Double.MAX_VALUE, p.computeDistance(DistanceStyle.ARC,gp), 0.0);
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.05, 0.15);
-    assertEquals(0.15 + 0.05, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.12);
-    assertEquals(0.12 + 0.0, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.15, 0.05);
-    assertEquals(Double.MAX_VALUE, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.25);
-    assertEquals(0.20 + 0.05, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.05);
-    assertEquals(0.0 + 0.05, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
-
-    // Compute path distances now
-    p = new GeoPath(PlanetModel.SPHERE, 0.1);
-    p.addPoint(0.0, 0.0);
-    p.addPoint(0.0, 0.1);
-    p.addPoint(0.0, 0.2);
-    p.done();
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.05, 0.15);
-    assertEquals(0.15 + 0.05, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.12);
-    assertEquals(0.12, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
-
-    // Now try a vertical path, and make sure distances are as expected
-    p = new GeoPath(PlanetModel.SPHERE, 0.1);
-    p.addPoint(-Math.PI * 0.25, -0.5);
-    p.addPoint(Math.PI * 0.25, -0.5);
-    p.done();
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
-    assertEquals(Double.MAX_VALUE, p.computeDistance(DistanceStyle.ARC,gp), 0.0);
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -1.0);
-    assertEquals(Double.MAX_VALUE, p.computeDistance(DistanceStyle.ARC,gp), 0.0);
-    gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.25 + 0.05, -0.5);
-    assertEquals(Math.PI * 0.5 + 0.05, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
-    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.25 - 0.05, -0.5);
-    assertEquals(0.0 + 0.05, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
-  }
-
-  @Test
-  public void testPathPointWithin() {
-    // Tests whether we can properly detect whether a point is within a path or not
-    GeoPath p;
-    GeoPoint gp;
-    p = new GeoPath(PlanetModel.SPHERE, 0.1);
-    // Build a diagonal path crossing the equator
-    p.addPoint(-0.2, -0.2);
-    p.addPoint(0.2, 0.2);
-    p.done();
-    // Test points on the path
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.2, -0.2);
-    assertTrue(p.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
-    assertTrue(p.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.1, 0.1);
-    assertTrue(p.isWithin(gp));
-    // Test points off the path
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.2, 0.2);
-    assertFalse(p.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0);
-    assertFalse(p.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.2, -0.2);
-    assertFalse(p.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
-    assertFalse(p.isWithin(gp));
-    // Repeat the test, but across the terminator
-    p = new GeoPath(PlanetModel.SPHERE, 0.1);
-    // Build a diagonal path crossing the equator
-    p.addPoint(-0.2, Math.PI - 0.2);
-    p.addPoint(0.2, -Math.PI + 0.2);
-    p.done();
-    // Test points on the path
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.2, Math.PI - 0.2);
-    assertTrue(p.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
-    assertTrue(p.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.1, -Math.PI + 0.1);
-    assertTrue(p.isWithin(gp));
-    // Test points off the path
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.2, -Math.PI + 0.2);
-    assertFalse(p.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0);
-    assertFalse(p.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.2, Math.PI - 0.2);
-    assertFalse(p.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
-    assertFalse(p.isWithin(gp));
-
-  }
-
-  @Test
-  public void testGetRelationship() {
-    GeoArea rect;
-    GeoPath p;
-    GeoPath c;
-    GeoPoint point;
-    GeoPoint pointApprox;
-    int relationship;
-    GeoArea area;
-    PlanetModel planetModel;
-    
-    planetModel = new PlanetModel(1.151145876105594, 0.8488541238944061);
-    c = new GeoPath(planetModel, 0.008726646259971648);
-    c.addPoint(-0.6925658899376476, 0.6316613927914589);
-    c.addPoint(0.27828548161836364, 0.6785795524104564);
-    c.done();
-    point = new GeoPoint(planetModel,-0.49298555067758226, 0.9892440995026406);
-    pointApprox = new GeoPoint(0.5110940362119821, 0.7774603209946239, -0.49984312299556544);
-    area = GeoAreaFactory.makeGeoArea(planetModel, 0.49937141144985997, 0.5161765426256085, 0.3337218719537796,0.8544419570901649, -0.6347692823688085, 0.3069696588119369);
-    assertTrue(!c.isWithin(point));
-    
-    // Start by testing the basic kinds of relationship, increasing in order of difficulty.
-
-    p = new GeoPath(PlanetModel.SPHERE, 0.1);
-    p.addPoint(-0.3, -0.3);
-    p.addPoint(0.3, 0.3);
-    p.done();
-    // Easiest: The path is wholly contains the georect
-    rect = new GeoRectangle(PlanetModel.SPHERE, 0.05, -0.05, -0.05, 0.05);
-    assertEquals(GeoArea.CONTAINS, rect.getRelationship(p));
-    // Next easiest: Some endpoints of the rectangle are inside, and some are outside.
-    rect = new GeoRectangle(PlanetModel.SPHERE, 0.05, -0.05, -0.05, 0.5);
-    assertEquals(GeoArea.OVERLAPS, rect.getRelationship(p));
-    // Now, all points are outside, but the figures intersect
-    rect = new GeoRectangle(PlanetModel.SPHERE, 0.05, -0.05, -0.5, 0.5);
-    assertEquals(GeoArea.OVERLAPS, rect.getRelationship(p));
-    // Finally, all points are outside, and the figures *do not* intersect
-    rect = new GeoRectangle(PlanetModel.SPHERE, 0.5, -0.5, -0.5, 0.5);
-    assertEquals(GeoArea.WITHIN, rect.getRelationship(p));
-    // Check that segment edge overlap detection works
-    rect = new GeoRectangle(PlanetModel.SPHERE, 0.1, 0.0, -0.1, 0.0);
-    assertEquals(GeoArea.OVERLAPS, rect.getRelationship(p));
-    rect = new GeoRectangle(PlanetModel.SPHERE, 0.2, 0.1, -0.2, -0.1);
-    assertEquals(GeoArea.DISJOINT, rect.getRelationship(p));
-    // Check if overlap at endpoints behaves as expected next
-    rect = new GeoRectangle(PlanetModel.SPHERE, 0.5, -0.5, -0.5, -0.35);
-    assertEquals(GeoArea.OVERLAPS, rect.getRelationship(p));
-    rect = new GeoRectangle(PlanetModel.SPHERE, 0.5, -0.5, -0.5, -0.45);
-    assertEquals(GeoArea.DISJOINT, rect.getRelationship(p));
-
-  }
-
-  @Test
-  public void testPathBounds() {
-    GeoPath c;
-    LatLonBounds b;
-    XYZBounds xyzb;
-    GeoPoint point;
-    int relationship;
-    GeoArea area;
-    PlanetModel planetModel;
-    
-    planetModel = new PlanetModel(0.751521665790406,1.248478334209594);
-    c = new GeoPath(planetModel, 0.7504915783575618);
-    c.addPoint(0.10869761172400265, 0.08895880215465272);
-    c.addPoint(0.22467878641991612, 0.10972973084229565);
-    c.addPoint(-0.7398772468744732, -0.4465812941383364);
-    c.addPoint(-0.18462055300079366, -0.6713857796763727);
-    c.done();
-    point = new GeoPoint(planetModel,-0.626645355125733,-1.409304625439381);
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    area = GeoAreaFactory.makeGeoArea(planetModel,
-      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
-    relationship = area.getRelationship(c);
-    assertTrue(relationship == GeoArea.WITHIN || relationship == GeoArea.OVERLAPS);
-    assertTrue(area.isWithin(point));
-    // No longer true due to fixed GeoPath waypoints.
-    //assertTrue(c.isWithin(point));
-    
-    c = new GeoPath(PlanetModel.WGS84, 0.6894050545377601);
-    c.addPoint(-0.0788176065762948, 0.9431251741731624);
-    c.addPoint(0.510387871458147, 0.5327078872484678);
-    c.addPoint(-0.5624521609859962, 1.5398841746888388);
-    c.addPoint(-0.5025171434638661, -0.5895998642788894);
-    c.done();
-    point = new GeoPoint(PlanetModel.WGS84, 0.023652082107211682, 0.023131910152748437);
-    //System.err.println("Point.x = "+point.x+"; point.y="+point.y+"; point.z="+point.z);
-    assertTrue(c.isWithin(point));
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84,
-      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
-    //System.err.println("minx="+xyzb.getMinimumX()+" maxx="+xyzb.getMaximumX()+" miny="+xyzb.getMinimumY()+" maxy="+xyzb.getMaximumY()+" minz="+xyzb.getMinimumZ()+" maxz="+xyzb.getMaximumZ());
-    //System.err.println("point.x="+point.x+" point.y="+point.y+" point.z="+point.z);
-    relationship = area.getRelationship(c);
-    assertTrue(relationship == GeoArea.WITHIN || relationship == GeoArea.OVERLAPS);
-    assertTrue(area.isWithin(point));
-    
-    c = new GeoPath(PlanetModel.WGS84, 0.7766715171374766);
-    c.addPoint(-0.2751718361148076, -0.7786721269011477);
-    c.addPoint(0.5728375851539309, -1.2700115736820465);
-    c.done();
-    point = new GeoPoint(PlanetModel.WGS84, -0.01580760332365284, -0.03956004622490505);
-    assertTrue(c.isWithin(point));
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84,
-      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
-    //System.err.println("minx="+xyzb.getMinimumX()+" maxx="+xyzb.getMaximumX()+" miny="+xyzb.getMinimumY()+" maxy="+xyzb.getMaximumY()+" minz="+xyzb.getMinimumZ()+" maxz="+xyzb.getMaximumZ());
-    //System.err.println("point.x="+point.x+" point.y="+point.y+" point.z="+point.z);
-    relationship = area.getRelationship(c);
-    assertTrue(relationship == GeoArea.WITHIN || relationship == GeoArea.OVERLAPS);
-    assertTrue(area.isWithin(point));
-
-    c = new GeoPath(PlanetModel.SPHERE, 0.1);
-    c.addPoint(-0.3, -0.3);
-    c.addPoint(0.3, 0.3);
-    c.done();
-
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(-0.4046919, b.getLeftLongitude(), 0.000001);
-    assertEquals(0.4046919, b.getRightLongitude(), 0.000001);
-    assertEquals(-0.3999999, b.getMinLatitude(), 0.000001);
-    assertEquals(0.3999999, b.getMaxLatitude(), 0.000001);
-
-  }
-
-  @Test
-  public void testCoLinear() {
-    // p1: (12,-90), p2: (11, -55), (129, -90)
-    GeoPath p = new GeoPath(PlanetModel.SPHERE, 0.1);
-    p.addPoint(toRadians(-90), toRadians(12));//south pole
-    p.addPoint(toRadians(-55), toRadians(11));
-    p.addPoint(toRadians(-90), toRadians(129));//south pole again
-    p.done();//at least test this doesn't bomb like it used too -- LUCENE-6520
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoPolygonTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoPolygonTest.java b/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoPolygonTest.java
deleted file mode 100755
index f1511b9..0000000
--- a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/GeoPolygonTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class GeoPolygonTest {
-
-
-  @Test
-  public void testPolygonPointWithin() {
-    GeoMembershipShape c;
-    GeoPoint gp;
-    List<GeoPoint> points;
-
-    points = new ArrayList<GeoPoint>();
-    points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.5));
-    points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.6));
-    points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.5));
-    points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.4));
-
-    c = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points, 0);
-    // Sample some points within
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.05, -0.5);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.05, -0.5);
-    assertTrue(c.isWithin(gp));
-    // Sample some nearby points outside
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.65);
-    assertFalse(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.35);
-    assertFalse(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.15, -0.5);
-    assertFalse(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.15, -0.5);
-    assertFalse(c.isWithin(gp));
-    // Random points outside
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
-    assertFalse(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.0);
-    assertFalse(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
-    assertFalse(c.isWithin(gp));
-
-    points = new ArrayList<GeoPoint>();
-    points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.5));
-    points.add(new GeoPoint(PlanetModel.SPHERE, -0.01, -0.6));
-    points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.7));
-    points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.8));
-    points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.7));
-    points.add(new GeoPoint(PlanetModel.SPHERE, 0.01, -0.6));
-    points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.5));
-    points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.4));
-        
-        /*
-        System.out.println("Points: ");
-        for (GeoPoint p : points) {
-            System.out.println(" "+p);
-        }
-        */
-
-    c = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points, 0);
-    // Sample some points within
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.05, -0.5);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.05, -0.5);
-    assertTrue(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.7);
-    assertTrue(c.isWithin(gp));
-    // Sample some nearby points outside
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.35);
-    assertFalse(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, -0.15, -0.5);
-    assertFalse(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.15, -0.5);
-    assertFalse(c.isWithin(gp));
-    // Random points outside
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
-    assertFalse(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.0);
-    assertFalse(c.isWithin(gp));
-    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
-    assertFalse(c.isWithin(gp));
-
-  }
-
-  @Test
-  public void testPolygonBounds() {
-    GeoMembershipShape c;
-    LatLonBounds b;
-    List<GeoPoint> points;
-    XYZBounds xyzb;
-    GeoPoint point;
-    GeoArea area;
-    
-    // BKD failure
-    points = new ArrayList<GeoPoint>();
-    points.add(new GeoPoint(PlanetModel.WGS84, -0.36716183577912814, 1.4836349969188696));
-    points.add(new GeoPoint(PlanetModel.WGS84, 0.7846038240742979, -0.02743348424931823));
-    points.add(new GeoPoint(PlanetModel.WGS84, -0.7376479402362607, -0.5072961758807019));
-    points.add(new GeoPoint(PlanetModel.WGS84, -0.3760415907667887, 1.4970455334565513));
-    
-    c = GeoPolygonFactory.makeGeoPolygon(PlanetModel.WGS84, points, 1);
-    
-    point = new GeoPoint(PlanetModel.WGS84, -0.01580760332365284, -0.03956004622490505);
-    assertTrue(c.isWithin(point));
-    xyzb = new XYZBounds();
-    c.getBounds(xyzb);
-    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84,
-      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
-    assertTrue(area.isWithin(point));
-    
-    points = new ArrayList<GeoPoint>();
-    points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.5));
-    points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.6));
-    points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.5));
-    points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.4));
-
-    c = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points, 0);
-
-    b = new LatLonBounds();
-    c.getBounds(b);
-    assertFalse(b.checkNoLongitudeBound());
-    assertFalse(b.checkNoTopLatitudeBound());
-    assertFalse(b.checkNoBottomLatitudeBound());
-    assertEquals(-0.6, b.getLeftLongitude(), 0.000001);
-    assertEquals(-0.4, b.getRightLongitude(), 0.000001);
-    assertEquals(-0.1, b.getMinLatitude(), 0.000001);
-    assertEquals(0.1, b.getMaxLatitude(), 0.000001);
-  }
-
-}


[07/50] [abbrv] lucene-solr git commit: LUCENE-7071: reduce byte copying costs of OfflineSorter

Posted by no...@apache.org.
LUCENE-7071: reduce byte copying costs of OfflineSorter


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

Branch: refs/heads/apiv2
Commit: 3d633c6e68ec7a2e47d398daae203582537593a4
Parents: 4df4cb0
Author: Mike McCandless <mi...@apache.org>
Authored: Mon Mar 7 18:12:10 2016 -0500
Committer: Mike McCandless <mi...@apache.org>
Committed: Mon Mar 7 18:12:10 2016 -0500

----------------------------------------------------------------------
 lucene/CHANGES.txt                              |  5 +++
 .../org/apache/lucene/util/ByteBlockPool.java   | 22 +++++++++++
 .../org/apache/lucene/util/BytesRefArray.java   | 41 +++++++++++++++-----
 .../org/apache/lucene/util/OfflineSorter.java   |  3 +-
 .../search/suggest/SortedInputIterator.java     | 16 ++++----
 5 files changed, 69 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/3d633c6e/lucene/CHANGES.txt
----------------------------------------------------------------------
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 16550c6..5e717d4 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -9,6 +9,11 @@ http://s.apache.org/luceneversions
 ======================= Lucene 6.1.0 =======================
 (No Changes)
 
+Optimizations
+
+* LUCENE-7071: Reduce bytes copying in OfflineSorter, giving ~10%
+  speedup on merging 2D LatLonPoint values (Mike McCandless)
+
 ======================= Lucene 6.0.0 =======================
 
 System Requirements

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/3d633c6e/lucene/core/src/java/org/apache/lucene/util/ByteBlockPool.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/ByteBlockPool.java b/lucene/core/src/java/org/apache/lucene/util/ByteBlockPool.java
index 5f8fd41..6bb12bd 100644
--- a/lucene/core/src/java/org/apache/lucene/util/ByteBlockPool.java
+++ b/lucene/core/src/java/org/apache/lucene/util/ByteBlockPool.java
@@ -280,6 +280,28 @@ public final class ByteBlockPool {
     return newUpto+3;
   }
 
+  /** Fill the provided {@link BytesRef} with the bytes at the specified offset/length slice.
+   *  This will avoid copying the bytes, if the slice fits into a single block; otherwise, it uses
+   *  the provided {@linkl BytesRefBuilder} to copy bytes over. */
+  void setBytesRef(BytesRefBuilder builder, BytesRef result, long offset, int length) {
+    result.length = length;
+
+    int bufferIndex = (int) (offset >> BYTE_BLOCK_SHIFT);
+    byte[] buffer = buffers[bufferIndex];
+    int pos = (int) (offset & BYTE_BLOCK_MASK);
+    if (pos + length <= BYTE_BLOCK_SIZE) {
+      // common case where the slice lives in a single block: just reference the buffer directly without copying
+      result.bytes = buffer;
+      result.offset = pos;
+    } else {
+      // uncommon case: the slice spans at least 2 blocks, so we must copy the bytes:
+      builder.grow(length);
+      result.bytes = builder.get().bytes;
+      result.offset = 0;
+      readBytes(offset, result.bytes, 0, length);
+    }
+  }
+
   // Fill in a BytesRef from term's length & bytes encoded in
   // byte block
   public void setBytesRef(BytesRef term, int textStart) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/3d633c6e/lucene/core/src/java/org/apache/lucene/util/BytesRefArray.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/BytesRefArray.java b/lucene/core/src/java/org/apache/lucene/util/BytesRefArray.java
index 47ca52b..a19b7da 100644
--- a/lucene/core/src/java/org/apache/lucene/util/BytesRefArray.java
+++ b/lucene/core/src/java/org/apache/lucene/util/BytesRefArray.java
@@ -108,7 +108,23 @@ public final class BytesRefArray {
     }
     throw new IndexOutOfBoundsException("index " + index
         + " must be less than the size: " + lastElement);
-    
+  }
+
+  /** Used only by sort below, to set a {@link BytesRef} with the specified slice, avoiding copying bytes in the common case when the slice
+   *  is contained in a single block in the byte block pool. */
+  private void setBytesRef(BytesRefBuilder spare, BytesRef result, int index) {
+    if (index < lastElement) {
+      int offset = offsets[index];
+      int length;
+      if (index == lastElement - 1) {
+        length = currentOffset - offset;
+      } else {
+        length = offsets[index + 1] - offset;
+      }
+      pool.setBytesRef(spare, result, offset, length);
+    } else {
+      throw new IndexOutOfBoundsException("index " + index + " must be less than the size: " + lastElement);
+    }
   }
   
   private int[] sort(final Comparator<BytesRef> comp) {
@@ -127,25 +143,30 @@ public final class BytesRefArray {
       @Override
       protected int compare(int i, int j) {
         final int idx1 = orderedEntries[i], idx2 = orderedEntries[j];
-        return comp.compare(get(scratch1, idx1), get(scratch2, idx2));
+        setBytesRef(scratch1, scratchBytes1, idx1);
+        setBytesRef(scratch2, scratchBytes2, idx2);
+        return comp.compare(scratchBytes1, scratchBytes2);
       }
       
       @Override
       protected void setPivot(int i) {
         final int index = orderedEntries[i];
-        pivot = get(pivotBuilder, index);
+        setBytesRef(pivotBuilder, pivot, index);
       }
       
       @Override
       protected int comparePivot(int j) {
         final int index = orderedEntries[j];
-        return comp.compare(pivot, get(scratch2, index));
+        setBytesRef(scratch2, scratchBytes2, index);
+        return comp.compare(pivot, scratchBytes2);
       }
 
-      private BytesRef pivot;
-      private final BytesRefBuilder pivotBuilder = new BytesRefBuilder(),
-          scratch1 = new BytesRefBuilder(),
-          scratch2 = new BytesRefBuilder();
+      private final BytesRef pivot = new BytesRef();
+      private final BytesRef scratchBytes1 = new BytesRef();
+      private final BytesRef scratchBytes2 = new BytesRef();
+      private final BytesRefBuilder pivotBuilder = new BytesRefBuilder();
+      private final BytesRefBuilder scratch1 = new BytesRefBuilder();
+      private final BytesRefBuilder scratch2 = new BytesRefBuilder();
     }.sort(0, size());
     return orderedEntries;
   }
@@ -173,6 +194,7 @@ public final class BytesRefArray {
    */
   public BytesRefIterator iterator(final Comparator<BytesRef> comp) {
     final BytesRefBuilder spare = new BytesRefBuilder();
+    final BytesRef result = new BytesRef();
     final int size = size();
     final int[] indices = comp == null ? null : sort(comp);
     return new BytesRefIterator() {
@@ -181,7 +203,8 @@ public final class BytesRefArray {
       @Override
       public BytesRef next() {
         if (pos < size) {
-          return get(spare, indices == null ? pos++ : indices[pos++]);
+          setBytesRef(spare, result, indices == null ? pos++ : indices[pos++]);
+          return result;
         }
         return null;
       }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/3d633c6e/lucene/core/src/java/org/apache/lucene/util/OfflineSorter.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/util/OfflineSorter.java b/lucene/core/src/java/org/apache/lucene/util/OfflineSorter.java
index 283dc1f..18e421b 100644
--- a/lucene/core/src/java/org/apache/lucene/util/OfflineSorter.java
+++ b/lucene/core/src/java/org/apache/lucene/util/OfflineSorter.java
@@ -282,7 +282,6 @@ public class OfflineSorter {
 
   /** Sort a single partition in-memory. */
   protected String sortPartition(TrackingDirectoryWrapper trackingDir) throws IOException {
-    BytesRefArray data = this.buffer;
 
     try (IndexOutput tempFile = trackingDir.createTempOutput(tempFileNamePrefix, "sort", IOContext.DEFAULT);
          ByteSequencesWriter out = getWriter(tempFile);) {
@@ -299,7 +298,7 @@ public class OfflineSorter {
       }
       
       // Clean up the buffer for the next partition.
-      data.clear();
+      buffer.clear();
 
       return tempFile.getName();
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/3d633c6e/lucene/suggest/src/java/org/apache/lucene/search/suggest/SortedInputIterator.java
----------------------------------------------------------------------
diff --git a/lucene/suggest/src/java/org/apache/lucene/search/suggest/SortedInputIterator.java b/lucene/suggest/src/java/org/apache/lucene/search/suggest/SortedInputIterator.java
index 2be1759..bc71e45 100644
--- a/lucene/suggest/src/java/org/apache/lucene/search/suggest/SortedInputIterator.java
+++ b/lucene/suggest/src/java/org/apache/lucene/search/suggest/SortedInputIterator.java
@@ -146,6 +146,7 @@ public class SortedInputIterator implements InputIterator {
     @Override
     public int compare(BytesRef left, BytesRef right) {
       // Make shallow copy in case decode changes the BytesRef:
+      assert left != right;
       leftScratch.bytes = left.bytes;
       leftScratch.offset = left.offset;
       leftScratch.length = left.length;
@@ -245,24 +246,24 @@ public class SortedInputIterator implements InputIterator {
   
   /** decodes the weight at the current position */
   protected long decode(BytesRef scratch, ByteArrayDataInput tmpInput) {
-    tmpInput.reset(scratch.bytes);
+    tmpInput.reset(scratch.bytes, scratch.offset, scratch.length);
     tmpInput.skipBytes(scratch.length - 8); // suggestion
-    scratch.length -= 8; // long
+    scratch.length -= Long.BYTES; // long
     return tmpInput.readLong();
   }
   
   /** decodes the contexts at the current position */
   protected Set<BytesRef> decodeContexts(BytesRef scratch, ByteArrayDataInput tmpInput) {
-    tmpInput.reset(scratch.bytes);
+    tmpInput.reset(scratch.bytes, scratch.offset, scratch.length);
     tmpInput.skipBytes(scratch.length - 2); //skip to context set size
     short ctxSetSize = tmpInput.readShort();
     scratch.length -= 2;
     final Set<BytesRef> contextSet = new HashSet<>();
     for (short i = 0; i < ctxSetSize; i++) {
-      tmpInput.setPosition(scratch.length - 2);
+      tmpInput.setPosition(scratch.offset + scratch.length - 2);
       short curContextLength = tmpInput.readShort();
       scratch.length -= 2;
-      tmpInput.setPosition(scratch.length - curContextLength);
+      tmpInput.setPosition(scratch.offset + scratch.length - curContextLength);
       BytesRef contextSpare = new BytesRef(curContextLength);
       tmpInput.readBytes(contextSpare.bytes, 0, curContextLength);
       contextSpare.length = curContextLength;
@@ -274,10 +275,11 @@ public class SortedInputIterator implements InputIterator {
   
   /** decodes the payload at the current position */
   protected BytesRef decodePayload(BytesRef scratch, ByteArrayDataInput tmpInput) {
-    tmpInput.reset(scratch.bytes);
+    tmpInput.reset(scratch.bytes, scratch.offset, scratch.length);
     tmpInput.skipBytes(scratch.length - 2); // skip to payload size
     short payloadLength = tmpInput.readShort(); // read payload size
-    tmpInput.setPosition(scratch.length - 2 - payloadLength); // setPosition to start of payload
+    assert payloadLength >= 0: payloadLength;
+    tmpInput.setPosition(scratch.offset + scratch.length - 2 - payloadLength); // setPosition to start of payload
     BytesRef payloadScratch = new BytesRef(payloadLength); 
     tmpInput.readBytes(payloadScratch.bytes, 0, payloadLength); // read payload
     payloadScratch.length = payloadLength;


[43/50] [abbrv] lucene-solr git commit: Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/lucene-solr

Posted by no...@apache.org.
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/lucene-solr


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

Branch: refs/heads/apiv2
Commit: d776f7b6bd7704283ec4db885b89cfb90f28ca75
Parents: 62b3aaa 02523d5
Author: Mike McCandless <mi...@apache.org>
Authored: Tue Mar 8 15:22:13 2016 -0500
Committer: Mike McCandless <mi...@apache.org>
Committed: Tue Mar 8 15:22:13 2016 -0500

----------------------------------------------------------------------
 solr/CHANGES.txt | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------



[15/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoLongitudeSlice.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoLongitudeSlice.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoLongitudeSlice.java
new file mode 100755
index 0000000..458cf8b
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoLongitudeSlice.java
@@ -0,0 +1,204 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Bounding box limited on left and right.
+ * The left-right maximum extent for this shape is PI; for anything larger, use
+ * {@link GeoWideLongitudeSlice}.
+ *
+ * @lucene.internal
+ */
+public class GeoLongitudeSlice extends GeoBaseBBox {
+  /** The left longitude of the slice */
+  protected final double leftLon;
+  /** The right longitude of the slice */
+  protected final double rightLon;
+  /** The left plane of the slice */
+  protected final SidedPlane leftPlane;
+  /** The right plane of the slice */
+  protected final SidedPlane rightPlane;
+  /** The notable points for the slice (north and south poles) */
+  protected final GeoPoint[] planePoints;
+  /** The center point of the slice */
+  protected final GeoPoint centerPoint;
+  /** A point on the edge of the slice */
+  protected final GeoPoint[] edgePoints;
+
+  /**
+   * Accepts only values in the following ranges: lon: {@code -PI -> PI}
+   *@param planetModel is the planet model.
+   *@param leftLon is the left longitude of the slice.
+   *@param rightLon is the right longitude of the slice.
+   */
+  public GeoLongitudeSlice(final PlanetModel planetModel, final double leftLon, double rightLon) {
+    super(planetModel);
+    // Argument checking
+    if (leftLon < -Math.PI || leftLon > Math.PI)
+      throw new IllegalArgumentException("Left longitude out of range");
+    if (rightLon < -Math.PI || rightLon > Math.PI)
+      throw new IllegalArgumentException("Right longitude out of range");
+    double extent = rightLon - leftLon;
+    if (extent < 0.0) {
+      extent += 2.0 * Math.PI;
+    }
+    if (extent > Math.PI)
+      throw new IllegalArgumentException("Width of rectangle too great");
+
+    this.leftLon = leftLon;
+    this.rightLon = rightLon;
+
+    final double sinLeftLon = Math.sin(leftLon);
+    final double cosLeftLon = Math.cos(leftLon);
+    final double sinRightLon = Math.sin(rightLon);
+    final double cosRightLon = Math.cos(rightLon);
+
+    // Normalize
+    while (leftLon > rightLon) {
+      rightLon += Math.PI * 2.0;
+    }
+    final double middleLon = (leftLon + rightLon) * 0.5;
+    this.centerPoint = new GeoPoint(planetModel, 0.0, middleLon);
+
+    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
+    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
+
+    this.planePoints = new GeoPoint[]{planetModel.NORTH_POLE, planetModel.SOUTH_POLE};
+    this.edgePoints = new GeoPoint[]{planetModel.NORTH_POLE};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    // Figuring out when we escalate to a special case requires some prefiguring
+    double currentLonSpan = rightLon - leftLon;
+    if (currentLonSpan < 0.0)
+      currentLonSpan += Math.PI * 2.0;
+    double newLeftLon = leftLon - angle;
+    double newRightLon = rightLon + angle;
+    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
+      newLeftLon = -Math.PI;
+      newRightLon = Math.PI;
+    }
+    return GeoBBoxFactory.makeGeoBBox(planetModel, Math.PI * 0.5, -Math.PI * 0.5, newLeftLon, newRightLon);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return leftPlane.isWithin(x, y, z) &&
+        rightPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public double getRadius() {
+    // Compute the extent and divide by two
+    double extent = rightLon - leftLon;
+    if (extent < 0.0)
+      extent += Math.PI * 2.0;
+    return Math.max(Math.PI * 0.5, extent * 0.5);
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    return centerPoint;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    return p.intersects(planetModel, leftPlane, notablePoints, planePoints, bounds, rightPlane) ||
+        p.intersects(planetModel, rightPlane, notablePoints, planePoints, bounds, leftPlane);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds
+      .addVerticalPlane(planetModel, leftLon, leftPlane, rightPlane)
+      .addVerticalPlane(planetModel, rightLon, rightPlane, leftPlane)
+      .addPoint(planetModel.NORTH_POLE)
+      .addPoint(planetModel.SOUTH_POLE);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    final int insideRectangle = isShapeInsideBBox(path);
+    if (insideRectangle == SOME_INSIDE)
+      return OVERLAPS;
+
+    final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
+
+    if (insideRectangle == ALL_INSIDE && insideShape)
+      return OVERLAPS;
+
+    if (path.intersects(leftPlane, planePoints, rightPlane) ||
+        path.intersects(rightPlane, planePoints, leftPlane)) {
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      return WITHIN;
+    }
+
+    if (insideShape) {
+      return CONTAINS;
+    }
+
+    return DISJOINT;
+  }
+
+  @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;
+    GeoLongitudeSlice other = (GeoLongitudeSlice) o;
+    return super.equals(other) && other.leftLon == leftLon && other.rightLon == rightLon;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    long temp = Double.doubleToLongBits(leftLon);
+    result = 31 * result + (int) (temp ^ (temp >>> 32));
+    temp = Double.doubleToLongBits(rightLon);
+    result = 31 * result + (int) (temp ^ (temp >>> 32));
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoLongitudeSlice: {planetmodel="+planetModel+", leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
+  }
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoMembershipShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoMembershipShape.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoMembershipShape.java
new file mode 100755
index 0000000..2c47971
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoMembershipShape.java
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Membership shapes have capabilities of both geohashing and membership
+ * determination.
+ *
+ * @lucene.experimental
+ */
+public interface GeoMembershipShape extends GeoShape, GeoOutsideDistance, Membership {
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoNorthLatitudeZone.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoNorthLatitudeZone.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoNorthLatitudeZone.java
new file mode 100644
index 0000000..2c94061
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoNorthLatitudeZone.java
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * This GeoBBox represents an area rectangle limited only in south latitude.
+ *
+ * @lucene.internal
+ */
+public class GeoNorthLatitudeZone extends GeoBaseBBox {
+  /** The bottom latitude of the zone */
+  protected final double bottomLat;
+  /** Cosine of the bottom latitude of the zone */
+  protected final double cosBottomLat;
+  /** The bottom plane of the zone */
+  protected final SidedPlane bottomPlane;
+  /** An interior point of the zone */
+  protected final GeoPoint interiorPoint;
+  /** Notable points: none */
+  protected final static GeoPoint[] planePoints = new GeoPoint[0];
+  /** A point on the bottom boundary */
+  protected final GeoPoint bottomBoundaryPoint;
+  /** A reference to the point on the boundary */
+  protected final GeoPoint[] edgePoints;
+
+  /** Constructor.
+   *@param planetModel is the planet model.
+   *@param bottomLat is the bottom latitude.
+   */
+  public GeoNorthLatitudeZone(final PlanetModel planetModel, final double bottomLat) {
+    super(planetModel);
+    this.bottomLat = bottomLat;
+
+    final double sinBottomLat = Math.sin(bottomLat);
+    this.cosBottomLat = Math.cos(bottomLat);
+
+    // Compute an interior point.  Pick one whose lat is between top and bottom.
+    final double middleLat = (Math.PI * 0.5 + bottomLat) * 0.5;
+    final double sinMiddleLat = Math.sin(middleLat);
+    this.interiorPoint = new GeoPoint(planetModel, sinMiddleLat, 0.0, Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 1.0);
+    this.bottomBoundaryPoint = new GeoPoint(planetModel, sinBottomLat, 0.0, Math.sqrt(1.0 - sinBottomLat * sinBottomLat), 1.0);
+
+    this.bottomPlane = new SidedPlane(interiorPoint, planetModel, sinBottomLat);
+
+    this.edgePoints = new GeoPoint[]{bottomBoundaryPoint};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    final double newTopLat = Math.PI * 0.5;
+    final double newBottomLat = bottomLat - angle;
+    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, -Math.PI, Math.PI);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return
+        bottomPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public double getRadius() {
+    // This is a bit tricky.  I guess we should interpret this as meaning the angle of a circle that
+    // would contain all the bounding box points, when starting in the "center".
+    if (bottomLat < 0.0)
+      return Math.PI;
+    double maxCosLat = cosBottomLat;
+    return maxCosLat * Math.PI;
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    return interiorPoint;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    return
+        p.intersects(planetModel, bottomPlane, notablePoints, planePoints, bounds);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds
+      .addHorizontalPlane(planetModel, bottomLat, bottomPlane);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    final int insideRectangle = isShapeInsideBBox(path);
+    if (insideRectangle == SOME_INSIDE)
+      return OVERLAPS;
+
+    final boolean insideShape = path.isWithin(bottomBoundaryPoint);
+
+    if (insideRectangle == ALL_INSIDE && insideShape)
+      return OVERLAPS;
+
+    // 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))
+      return OVERLAPS;
+
+    // There is another case for latitude zones only.  This is when the boundaries of the shape all fit
+    // within the zone, but the shape includes areas outside the zone crossing a pole.
+    // In this case, the above "overlaps" check is insufficient.  We also need to check a point on either boundary
+    // whether it is within the shape.  If both such points are within, then CONTAINS is the right answer.  If
+    // one such point is within, then OVERLAPS is the right answer.
+
+    if (insideShape)
+      return CONTAINS;
+
+    if (insideRectangle == ALL_INSIDE)
+      return WITHIN;
+
+    return DISJOINT;
+  }
+
+  @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;
+    GeoNorthLatitudeZone other = (GeoNorthLatitudeZone) o;
+    return super.equals(other) && other.bottomBoundaryPoint.equals(bottomBoundaryPoint);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + bottomBoundaryPoint.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoNorthLatitudeZone: {planetmodel="+planetModel+", bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + ")}";
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoNorthRectangle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoNorthRectangle.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoNorthRectangle.java
new file mode 100644
index 0000000..a2b6f1b
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoNorthRectangle.java
@@ -0,0 +1,263 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * 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
+ * {@link GeoWideNorthRectangle}.
+ *
+ * @lucene.internal
+ */
+public class GeoNorthRectangle extends GeoBaseBBox {
+  /** The bottom latitude of the rectangle */
+  protected final double bottomLat;
+  /** The left longitude */
+  protected final double leftLon;
+  /** The right longitude */
+  protected final double rightLon;
+  /** Cosine of the middle latitude */
+  protected final double cosMiddleLat;
+  /** Lower right hand corner point */
+  protected final GeoPoint LRHC;
+  /** Lower left hand corner point */
+  protected final GeoPoint LLHC;
+  /** Bottom edge plane */
+  protected final SidedPlane bottomPlane;
+  /** Left-side plane */
+  protected final SidedPlane leftPlane;
+  /** Right-side plane */
+  protected final SidedPlane rightPlane;
+  /** Bottom plane notable points */
+  protected final GeoPoint[] bottomPlanePoints;
+  /** Left plane notable points */
+  protected final GeoPoint[] leftPlanePoints;
+  /** Right plane notable points */
+  protected final GeoPoint[] rightPlanePoints;
+  /** Center point */
+  protected final GeoPoint centerPoint;
+  /** A point on the edge */
+  protected final GeoPoint[] edgePoints;
+
+  /**
+   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
+   *@param planetModel is the planet model.
+   *@param bottomLat is the bottom latitude.
+   *@param leftLon is the left longitude.
+   *@param rightLon is the right longitude.
+   */
+  public GeoNorthRectangle(final PlanetModel planetModel, final double bottomLat, final double leftLon, double rightLon) {
+    super(planetModel);
+    // Argument checking
+    if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
+      throw new IllegalArgumentException("Bottom latitude out of range");
+    if (leftLon < -Math.PI || leftLon > Math.PI)
+      throw new IllegalArgumentException("Left longitude out of range");
+    if (rightLon < -Math.PI || rightLon > Math.PI)
+      throw new IllegalArgumentException("Right longitude out of range");
+    double extent = rightLon - leftLon;
+    if (extent < 0.0) {
+      extent += 2.0 * Math.PI;
+    }
+    if (extent > Math.PI)
+      throw new IllegalArgumentException("Width of rectangle too great");
+
+    this.bottomLat = bottomLat;
+    this.leftLon = leftLon;
+    this.rightLon = rightLon;
+
+    final double sinBottomLat = Math.sin(bottomLat);
+    final double cosBottomLat = Math.cos(bottomLat);
+    final double sinLeftLon = Math.sin(leftLon);
+    final double cosLeftLon = Math.cos(leftLon);
+    final double sinRightLon = Math.sin(rightLon);
+    final double cosRightLon = Math.cos(rightLon);
+
+    // Now build the points
+    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);
+    this.cosMiddleLat = Math.cos(middleLat);
+    // Normalize
+    while (leftLon > rightLon) {
+      rightLon += Math.PI * 2.0;
+    }
+    final double middleLon = (leftLon + rightLon) * 0.5;
+    final double sinMiddleLon = Math.sin(middleLon);
+    final double cosMiddleLon = Math.cos(middleLon);
+
+    this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
+
+    this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
+    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
+    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
+
+    this.bottomPlanePoints = new GeoPoint[]{LLHC, LRHC};
+    this.leftPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LLHC};
+    this.rightPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LRHC};
+
+    this.edgePoints = new GeoPoint[]{planetModel.NORTH_POLE};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    final double newTopLat = Math.PI * 0.5;
+    final double newBottomLat = bottomLat - angle;
+    // Figuring out when we escalate to a special case requires some prefiguring
+    double currentLonSpan = rightLon - leftLon;
+    if (currentLonSpan < 0.0)
+      currentLonSpan += Math.PI * 2.0;
+    double newLeftLon = leftLon - angle;
+    double newRightLon = rightLon + angle;
+    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
+      newLeftLon = -Math.PI;
+      newRightLon = Math.PI;
+    }
+    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return
+        bottomPlane.isWithin(x, y, z) &&
+            leftPlane.isWithin(x, y, z) &&
+            rightPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public double getRadius() {
+    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
+    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
+    // the distance to the right or left edge from the center.
+    final double centerAngle = (rightLon - (rightLon + leftLon) * 0.5) * cosMiddleLat;
+    final double bottomAngle = centerPoint.arcDistance(LLHC);
+    return Math.max(centerAngle, bottomAngle);
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  /**
+   * Returns the center of a circle into which the area will be inscribed.
+   *
+   * @return the center.
+   */
+  @Override
+  public GeoPoint getCenter() {
+    return centerPoint;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    return
+        p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, leftPlane, rightPlane) ||
+            p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, bottomPlane) ||
+            p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, bottomPlane);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds
+      .addHorizontalPlane(planetModel, bottomLat, bottomPlane, leftPlane, rightPlane)
+      .addVerticalPlane(planetModel, leftLon, leftPlane, bottomPlane, rightPlane)
+      .addVerticalPlane(planetModel, rightLon, rightPlane, bottomPlane, leftPlane)
+      .addPoint(LLHC).addPoint(LRHC).addPoint(planetModel.NORTH_POLE);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    //System.err.println(this+" getrelationship with "+path);
+    final int insideRectangle = isShapeInsideBBox(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some inside");
+      return OVERLAPS;
+    }
+
+    final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
+
+    if (insideRectangle == ALL_INSIDE && insideShape) {
+      //System.err.println(" inside of each other");
+      return OVERLAPS;
+    }
+
+    if (
+        path.intersects(bottomPlane, bottomPlanePoints, leftPlane, rightPlane) ||
+            path.intersects(leftPlane, leftPlanePoints, bottomPlane, rightPlane) ||
+            path.intersects(rightPlane, rightPlanePoints, leftPlane, bottomPlane)) {
+      //System.err.println(" edges intersect");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      //System.err.println(" shape inside rectangle");
+      return WITHIN;
+    }
+
+    if (insideShape) {
+      //System.err.println(" shape contains rectangle");
+      return CONTAINS;
+    }
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @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;
+    GeoNorthRectangle other = (GeoNorthRectangle) o;
+    return super.equals(other) && other.LLHC.equals(LLHC) && other.LRHC.equals(LRHC);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + LLHC.hashCode();
+    result = 31 * result + LRHC.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoNorthRectangle: {planetmodel="+planetModel+", bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
+  }
+}
+  
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoOutsideDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoOutsideDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoOutsideDistance.java
new file mode 100644
index 0000000..717854c
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoOutsideDistance.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Implemented by Geo3D shapes that can compute the distance from a point to the closest outside edge.
+ *
+ * @lucene.experimental
+ */
+public interface GeoOutsideDistance extends Membership {
+  
+  // The following methods compute distances from the shape to a point
+  // expected to be OUTSIDE the shape.  Typically a value of 0.0
+  // is returned for points that happen to be within the shape.
+  
+  /**
+   * Compute this shape's distance to the GeoPoint.
+   * A return value of 0.0 should be returned for
+   * points inside of the shape.
+   * @param distanceStyle is the distance style.
+   * @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);
+  }
+
+  /**
+   * Compute this shape's distance to the GeoPoint.
+   * A return value of 0.0 should be returned for
+   * points inside of the shape.
+   * @param distanceStyle is the distance style.
+   * @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 distance.
+   */
+  public double computeOutsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
+
+}
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPath.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPath.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPath.java
new file mode 100755
index 0000000..a5b8b9b
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPath.java
@@ -0,0 +1,797 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 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 GeoBaseDistanceShape {
+  /** The cutoff angle (width) */
+  protected final double cutoffAngle;
+
+  /** Sine of cutoff angle */
+  protected final double sinAngle;
+  /** Cosine of cutoff angle */
+  protected final double cosAngle;
+
+  /** The original list of path points */
+  protected final List<GeoPoint> points = new ArrayList<GeoPoint>();
+  
+  /** A list of SegmentEndpoints */
+  protected List<SegmentEndpoint> endPoints;
+  /** A list of PathSegments */
+  protected List<PathSegment> segments;
+
+  /** A point on the edge */
+  protected GeoPoint[] edgePoints;
+
+  /** Set to true if path has been completely constructed */
+  protected boolean isDone = false;
+  
+  /** Constructor.
+   *@param planetModel is the planet model.
+   *@param maxCutoffAngle is the width of the path, measured as an angle.
+   *@param pathPoints are the points in the path.
+   */
+  public GeoPath(final PlanetModel planetModel, final double maxCutoffAngle, final GeoPoint[] pathPoints) {
+    this(planetModel, maxCutoffAngle);
+    Collections.addAll(points, pathPoints);
+    done();
+  }
+  
+  /** Piece-wise constructor.  Use in conjunction with addPoint() and done().
+   *@param planetModel is the planet model.
+   *@param maxCutoffAngle is the width of the path, measured as an angle.
+   */
+  public GeoPath(final PlanetModel planetModel, final double maxCutoffAngle) {
+    super(planetModel);
+    if (maxCutoffAngle <= 0.0 || maxCutoffAngle > Math.PI * 0.5)
+      throw new IllegalArgumentException("Cutoff angle out of bounds");
+    this.cutoffAngle = maxCutoffAngle;
+    this.cosAngle = Math.cos(maxCutoffAngle);
+    this.sinAngle = Math.sin(maxCutoffAngle);
+  }
+
+  /** Add a point to the path.
+   *@param lat is the latitude of the point.
+   *@param lon is the longitude of the point.
+   */
+  public void addPoint(final double lat, final double lon) {
+    if (isDone)
+      throw new IllegalStateException("Can't call addPoint() if done() already called");
+    points.add(new GeoPoint(planetModel, lat, lon));
+  }
+  
+  /** Complete the path.
+   */
+  public void done() {
+    if (isDone)
+      throw new IllegalStateException("Can't call done() twice");
+    if (points.size() == 0)
+      throw new IllegalArgumentException("Path must have at least one point");
+    isDone = true;
+
+    endPoints = new ArrayList<>(points.size());
+    segments = new ArrayList<>(points.size());
+    // Compute an offset to use for all segments.  This will be based on the minimum magnitude of
+    // the entire ellipsoid.
+    final double cutoffOffset = this.sinAngle * planetModel.getMinimumMagnitude();
+    
+    // First, build all segments.  We'll then go back and build corresponding segment endpoints.
+    GeoPoint lastPoint = null;
+    for (final GeoPoint end : points) {
+      if (lastPoint != null) {
+        final Plane normalizedConnectingPlane = new Plane(lastPoint, end);
+        if (normalizedConnectingPlane == null) {
+          continue;
+        }
+        segments.add(new PathSegment(planetModel, lastPoint, end, normalizedConnectingPlane, cutoffOffset));
+      }
+      lastPoint = end;
+    }
+    
+    if (segments.size() == 0) {
+      // Simple circle
+      double lat = points.get(0).getLatitude();
+      double lon = points.get(0).getLongitude();
+      // Compute two points on the circle, with the right angle from the center.  We'll use these
+      // to obtain the perpendicular plane to the circle.
+      double upperLat = lat + cutoffAngle;
+      double upperLon = lon;
+      if (upperLat > Math.PI * 0.5) {
+        upperLon += Math.PI;
+        if (upperLon > Math.PI)
+          upperLon -= 2.0 * Math.PI;
+        upperLat = Math.PI - upperLat;
+      }
+      double lowerLat = lat - cutoffAngle;
+      double lowerLon = lon;
+      if (lowerLat < -Math.PI * 0.5) {
+        lowerLon += Math.PI;
+        if (lowerLon > Math.PI)
+          lowerLon -= 2.0 * Math.PI;
+        lowerLat = -Math.PI - lowerLat;
+      }
+      final GeoPoint upperPoint = new GeoPoint(planetModel, upperLat, upperLon);
+      final GeoPoint lowerPoint = new GeoPoint(planetModel, lowerLat, lowerLon);
+      final GeoPoint point = points.get(0);
+      
+      // Construct normal plane
+      final Plane normalPlane = Plane.constructNormalizedZPlane(upperPoint, lowerPoint, point);
+
+      final SegmentEndpoint onlyEndpoint = new SegmentEndpoint(point, normalPlane, upperPoint, lowerPoint);
+      endPoints.add(onlyEndpoint);
+      this.edgePoints = new GeoPoint[]{onlyEndpoint.circlePlane.getSampleIntersectionPoint(planetModel, normalPlane)};
+      return;
+    }
+    
+    // Create segment endpoints.  Use an appropriate constructor for the start and end of the path.
+    for (int i = 0; i < segments.size(); i++) {
+      final PathSegment currentSegment = segments.get(i);
+      
+      if (i == 0) {
+        // Starting endpoint
+        final SegmentEndpoint startEndpoint = new SegmentEndpoint(currentSegment.start, 
+          currentSegment.startCutoffPlane, currentSegment.ULHC, currentSegment.LLHC);
+        endPoints.add(startEndpoint);
+        this.edgePoints = new GeoPoint[]{currentSegment.ULHC};
+        continue;
+      }
+      
+      // General intersection case
+      final PathSegment prevSegment = segments.get(i-1);
+      // We construct four separate planes, and evaluate which one includes all interior points with least overlap
+      final SidedPlane candidate1 = SidedPlane.constructNormalizedThreePointSidedPlane(currentSegment.start, prevSegment.URHC, currentSegment.ULHC, currentSegment.LLHC);
+      final SidedPlane candidate2 = SidedPlane.constructNormalizedThreePointSidedPlane(currentSegment.start, currentSegment.ULHC, currentSegment.LLHC, prevSegment.LRHC);
+      final SidedPlane candidate3 = SidedPlane.constructNormalizedThreePointSidedPlane(currentSegment.start, currentSegment.LLHC, prevSegment.LRHC, prevSegment.URHC);
+      final SidedPlane candidate4 = SidedPlane.constructNormalizedThreePointSidedPlane(currentSegment.start, prevSegment.LRHC, prevSegment.URHC, currentSegment.ULHC);
+
+      if (candidate1 == null && candidate2 == null && candidate3 == null && candidate4 == null) {
+        // The planes are identical.  We wouldn't need a circle at all except for the possibility of
+        // backing up, which is hard to detect here.
+        final SegmentEndpoint midEndpoint = new SegmentEndpoint(currentSegment.start, 
+          prevSegment.endCutoffPlane, currentSegment.startCutoffPlane, currentSegment.ULHC, currentSegment.LLHC);
+        //don't need a circle at all.  Special constructor...
+        endPoints.add(midEndpoint);
+      } else {
+        endPoints.add(new SegmentEndpoint(currentSegment.start,
+          prevSegment.endCutoffPlane, currentSegment.startCutoffPlane,
+          prevSegment.URHC, prevSegment.LRHC,
+          currentSegment.ULHC, currentSegment.LLHC,
+          candidate1, candidate2, candidate3, candidate4));
+      }
+    }
+    // Do final endpoint
+    final PathSegment lastSegment = segments.get(segments.size()-1);
+    endPoints.add(new SegmentEndpoint(lastSegment.end,
+      lastSegment.endCutoffPlane, lastSegment.URHC, lastSegment.LRHC));
+
+  }
+
+  @Override
+  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(planetModel, distanceStyle, x,y,z);
+      if (distance != Double.MAX_VALUE)
+        return currentDistance + distance;
+      currentDistance += segment.fullPathDistance(distanceStyle);
+    }
+
+    int segmentIndex = 0;
+    currentDistance = 0.0;
+    for (SegmentEndpoint endpoint : endPoints) {
+      double distance = endpoint.pathDistance(distanceStyle, x, y, z);
+      if (distance != Double.MAX_VALUE)
+        return currentDistance + distance;
+      if (segmentIndex < segments.size())
+        currentDistance += segments.get(segmentIndex++).fullPathDistance(distanceStyle);
+    }
+
+    return Double.MAX_VALUE;
+  }
+
+  @Override
+  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    double minDistance = Double.MAX_VALUE;
+    for (final SegmentEndpoint endpoint : endPoints) {
+      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;
+    }
+    return minDistance;
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    for (SegmentEndpoint pathPoint : endPoints) {
+      if (pathPoint.isWithin(x, y, z))
+        return true;
+    }
+    for (PathSegment pathSegment : segments) {
+      if (pathSegment.isWithin(x, y, z))
+        return true;
+    }
+    return false;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane plane, final GeoPoint[] notablePoints, final Membership... bounds) {
+    // We look for an intersection with any of the exterior edges of the path.
+    // We also have to look for intersections with the cones described by the endpoints.
+    // Return "true" if any such intersections are found.
+
+    // For plane intersections, the basic idea is to come up with an equation of the line that is
+    // the intersection (if any).  Then, find the intersections with the unit sphere (if any).  If
+    // any of the intersection points are within the bounds, then we've detected an intersection.
+    // Well, sort of.  We can detect intersections also due to overlap of segments with each other.
+    // But that's an edge case and we won't be optimizing for it.
+    //System.err.println(" Looking for intersection of plane "+plane+" with path "+this);
+    for (final SegmentEndpoint pathPoint : endPoints) {
+      if (pathPoint.intersects(planetModel, plane, notablePoints, bounds)) {
+        return true;
+      }
+    }
+
+    for (final PathSegment pathSegment : segments) {
+      if (pathSegment.intersects(planetModel, plane, notablePoints, bounds)) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  @Override
+  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.
+    for (PathSegment pathSegment : segments) {
+      pathSegment.getBounds(planetModel, bounds);
+    }
+    for (SegmentEndpoint pathPoint : endPoints) {
+      pathPoint.getBounds(planetModel, bounds);
+    }
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof GeoPath))
+      return false;
+    GeoPath p = (GeoPath) o;
+    if (!super.equals(p))
+      return false;
+    if (cutoffAngle != p.cutoffAngle)
+      return false;
+    return points.equals(p.points);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    long temp = Double.doubleToLongBits(cutoffAngle);
+    result = 31 * result + (int) (temp ^ (temp >>> 32));
+    result = 31 * result + points.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoPath: {planetmodel=" + planetModel+", width=" + cutoffAngle + "(" + cutoffAngle * 180.0 / Math.PI + "), points={" + points + "}}";
+  }
+
+  /**
+   * This is precalculated data for segment endpoint.
+   * Note well: This is not necessarily a circle.  There are four cases:
+   * (1) The path consists of a single endpoint.  In this case, we build a simple circle with the proper cutoff offset.
+   * (2) This is the end of a path.  The circle plane must be constructed to go through two supplied points and be perpendicular to a connecting plane.
+   * (2.5) Intersection, but the path on both sides is linear.  We generate a circle, but we use the cutoff planes to limit its influence in the straight line case.
+   * (3) This is an intersection in a path.  We are supplied FOUR planes.  If there are intersections within bounds for both upper and lower, then
+   *    we generate no circle at all.  If there is one intersection only, then we generate a plane that includes that intersection, as well as the remaining
+   *    cutoff plane/edge plane points.
+   */
+  public static class SegmentEndpoint {
+    /** The center point of the endpoint */
+    public final GeoPoint point;
+    /** A plane describing the circle */
+    public final SidedPlane circlePlane;
+    /** Pertinent cutoff planes from adjoining segments */
+    public final Membership[] cutoffPlanes;
+    /** Notable points for this segment endpoint */
+    public final GeoPoint[] notablePoints;
+    /** No notable points from the circle itself */
+    public final static GeoPoint[] circlePoints = new GeoPoint[0];
+    /** Null membership */
+    public final static Membership[] NO_MEMBERSHIP = new Membership[0];
+    
+    /** Base case.  Does nothing at all.
+     */
+    public SegmentEndpoint(final GeoPoint point) {
+      this.point = point;
+      this.circlePlane = null;
+      this.cutoffPlanes = null;
+      this.notablePoints = null;
+    }
+    
+    /** Constructor for case (1).
+     * Generate a simple circle cutoff plane.
+     *@param point is the center point.
+     *@param upperPoint is a point that must be on the circle plane.
+     *@param lowerPoint is another point that must be on the circle plane.
+     */
+    public SegmentEndpoint(final GeoPoint point, final Plane normalPlane, final GeoPoint upperPoint, final GeoPoint lowerPoint) {
+      this.point = 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 = NO_MEMBERSHIP;
+      this.notablePoints = circlePoints;
+    }
+    
+    /** Constructor for case (2).
+     * Generate an endpoint, given a single cutoff plane plus upper and lower edge points.
+     *@param point is the center point.
+     *@param cutoffPlane is the plane from the adjoining path segment marking the boundary between this endpoint and that segment.
+     *@param topEdgePoint is a point on the cutoffPlane that should be also on the circle plane.
+     *@param bottomEdgePoint is another point on the cutoffPlane that should be also on the circle plane.
+     */
+    public SegmentEndpoint(final GeoPoint point,
+      final SidedPlane cutoffPlane, final GeoPoint topEdgePoint, final GeoPoint bottomEdgePoint) {
+      this.point = point;
+      this.cutoffPlanes = new Membership[]{new SidedPlane(cutoffPlane)};
+      this.notablePoints = new GeoPoint[]{topEdgePoint, bottomEdgePoint};
+      // To construct the plane, we now just need D, which is simply the negative of the evaluation of the circle normal vector at one of the points.
+      this.circlePlane = SidedPlane.constructNormalizedPerpendicularSidedPlane(point, cutoffPlane, topEdgePoint, bottomEdgePoint);
+    }
+
+    /** Constructor for case (2.5).
+     * Generate an endpoint, given two cutoff planes plus upper and lower edge points.
+     *@param point is the center.
+     *@param cutoffPlane1 is one adjoining path segment cutoff plane.
+     *@param cutoffPlane2 is another adjoining path segment cutoff plane.
+     *@param topEdgePoint is a point on the cutoffPlane that should be also on the circle plane.
+     *@param bottomEdgePoint is another point on the cutoffPlane that should be also on the circle plane.
+     */
+    public SegmentEndpoint(final GeoPoint point,
+      final SidedPlane cutoffPlane1, final SidedPlane cutoffPlane2, final GeoPoint topEdgePoint, final GeoPoint bottomEdgePoint) {
+      this.point = point;
+      this.cutoffPlanes = new Membership[]{new SidedPlane(cutoffPlane1), new SidedPlane(cutoffPlane2)};
+      this.notablePoints = new GeoPoint[]{topEdgePoint, bottomEdgePoint};
+      // To construct the plane, we now just need D, which is simply the negative of the evaluation of the circle normal vector at one of the points.
+      this.circlePlane = SidedPlane.constructNormalizedPerpendicularSidedPlane(point, cutoffPlane1, topEdgePoint, bottomEdgePoint);
+    }
+    
+    /** Constructor for case (3).
+     * Generate an endpoint for an intersection, given four points.
+     *@param point is the center.
+     *@param prevCutoffPlane is the previous adjoining segment cutoff plane.
+     *@param nextCutoffPlane is the next path segment cutoff plane.
+     *@param notCand2Point is a point NOT on candidate2.
+     *@param notCand1Point is a point NOT on candidate1.
+     *@param notCand3Point is a point NOT on candidate3.
+     *@param notCand4Point is a point NOT on candidate4.
+     *@param candidate1 one of four candidate circle planes.
+     *@param candidate2 one of four candidate circle planes.
+     *@param candidate3 one of four candidate circle planes.
+     *@param candidate4 one of four candidate circle planes.
+     */
+    public SegmentEndpoint(final GeoPoint point,
+      final SidedPlane prevCutoffPlane, final SidedPlane nextCutoffPlane,
+      final GeoPoint notCand2Point, final GeoPoint notCand1Point,
+      final GeoPoint notCand3Point, final GeoPoint notCand4Point,
+      final SidedPlane candidate1, final SidedPlane candidate2, final SidedPlane candidate3, final SidedPlane candidate4) {
+      // Note: What we really need is a single plane that goes through all four points.
+      // Since that's not possible in the ellipsoid case (because three points determine a plane, not four), we
+      // need an approximation that at least creates a boundary that has no interruptions.
+      // There are three obvious choices for the third point: either (a) one of the two remaining points, or (b) the top or bottom edge
+      // intersection point.  (a) has no guarantee of continuity, while (b) is capable of producing something very far from a circle if
+      // the angle between segments is acute.
+      // The solution is to look for the side (top or bottom) that has an intersection within the shape.  We use the two points from
+      // the opposite side to determine the plane, AND we pick the third to be either of the two points on the intersecting side
+      // PROVIDED that the other point is within the final circle we come up with.
+      this.point = point;
+      
+      // We construct four separate planes, and evaluate which one includes all interior points with least overlap
+      // (Constructed beforehand because we need them for degeneracy check)
+
+      final boolean cand1IsOtherWithin = candidate1!=null?candidate1.isWithin(notCand1Point):false;
+      final boolean cand2IsOtherWithin = candidate2!=null?candidate2.isWithin(notCand2Point):false;
+      final boolean cand3IsOtherWithin = candidate3!=null?candidate3.isWithin(notCand3Point):false;
+      final boolean cand4IsOtherWithin = candidate4!=null?candidate4.isWithin(notCand4Point):false;
+      
+      if (cand1IsOtherWithin && cand2IsOtherWithin && cand3IsOtherWithin && cand4IsOtherWithin) {
+        // The only way we should see both within is if all four points are coplanar.  In that case, we default to the simplest treatment.
+        this.circlePlane = candidate1;  // doesn't matter which
+        this.notablePoints = new GeoPoint[]{notCand2Point, notCand3Point, notCand1Point, notCand4Point};
+        this.cutoffPlanes = new Membership[]{new SidedPlane(prevCutoffPlane), new SidedPlane(nextCutoffPlane)};
+      } else if (cand1IsOtherWithin) {
+        // Use candidate1, and DON'T include prevCutoffPlane in the cutoff planes list
+        this.circlePlane = candidate1;
+        this.notablePoints = new GeoPoint[]{notCand2Point, notCand3Point, notCand4Point};
+        this.cutoffPlanes = new Membership[]{new SidedPlane(nextCutoffPlane)};
+      } else if (cand2IsOtherWithin) {
+        // Use candidate2
+        this.circlePlane = candidate2;
+        this.notablePoints = new GeoPoint[]{notCand3Point, notCand4Point, notCand1Point};
+        this.cutoffPlanes = new Membership[]{new SidedPlane(nextCutoffPlane)};
+      } else if (cand3IsOtherWithin) {
+        this.circlePlane = candidate3;
+        this.notablePoints = new GeoPoint[]{notCand4Point, notCand1Point, notCand2Point};
+        this.cutoffPlanes = new Membership[]{new SidedPlane(prevCutoffPlane)};
+      } else if (cand4IsOtherWithin) {
+        this.circlePlane = candidate4;
+        this.notablePoints = new GeoPoint[]{notCand1Point, notCand2Point, notCand3Point};
+        this.cutoffPlanes = new Membership[]{new SidedPlane(prevCutoffPlane)};
+      } else {
+        // dunno what happened
+        throw new RuntimeException("Couldn't come up with a plane through three points that included the fourth");
+      }
+    }
+
+    /** Check if point is within this endpoint.
+     *@param point is the point.
+     *@return true of within.
+     */
+    public boolean isWithin(final Vector point) {
+      if (circlePlane == null)
+        return false;
+      if (!circlePlane.isWithin(point))
+        return false;
+      for (final Membership m : cutoffPlanes) {
+        if (!m.isWithin(point)) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    /** Check if point is within this endpoint.
+     *@param x is the point x.
+     *@param y is the point y.
+     *@param z is the point z.
+     *@return true of within.
+     */
+    public boolean isWithin(final double x, final double y, final double z) {
+      if (circlePlane == null)
+        return false;
+      if (!circlePlane.isWithin(x, y, z))
+        return false;
+      for (final Membership m : cutoffPlanes) {
+        if (!m.isWithin(x,y,z)) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    /** Compute interior path distance.
+     *@param distanceStyle is the distance style.
+     *@param x is the point x.
+     *@param y is the point y.
+     *@param z is the point z.
+     *@return the distance metric.
+     */
+    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 distanceStyle.computeDistance(this.point, x, y, z);
+    }
+
+    /** Compute external distance.
+     *@param distanceStyle is the distance style.
+     *@param x is the point x.
+     *@param y is the point y.
+     *@param z is the point z.
+     *@return the distance metric.
+     */
+    public double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+      return distanceStyle.computeDistance(this.point, x, y, z);
+    }
+
+    /** Determine if this endpoint intersects a specified plane.
+     *@param planetModel is the planet model.
+     *@param p is the plane.
+     *@param notablePoints are the points associated with the plane.
+     *@param bounds are any bounds which the intersection must lie within.
+     *@return true if there is a matching intersection.
+     */
+    public boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
+      //System.err.println("  looking for intersection between plane "+p+" and circle "+circlePlane+" on proper side of "+cutoffPlanes+" within "+bounds);
+      if (circlePlane == null)
+        return false;
+      return circlePlane.intersects(planetModel, p, notablePoints, this.notablePoints, bounds, this.cutoffPlanes);
+    }
+
+    /** Get the bounds for a segment endpoint.
+     *@param planetModel is the planet model.
+     *@param bounds are the bounds to be modified.
+     */
+    public void getBounds(final PlanetModel planetModel, Bounds bounds) {
+      bounds.addPoint(point);
+      if (circlePlane == null)
+        return;
+      bounds.addPlane(planetModel, circlePlane);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (!(o instanceof SegmentEndpoint))
+        return false;
+      SegmentEndpoint other = (SegmentEndpoint) o;
+      return point.equals(other.point);
+    }
+
+    @Override
+    public int hashCode() {
+      return point.hashCode();
+    }
+
+    @Override
+    public String toString() {
+      return point.toString();
+    }
+  }
+
+  /**
+   * This is the pre-calculated data for a path segment.
+   */
+  public static class PathSegment {
+    /** Starting point of the segment */
+    public final GeoPoint start;
+    /** End point of the segment */
+    public final GeoPoint end;
+    /** Place to keep any complete segment distances we've calculated so far */
+    public final Map<DistanceStyle,Double> fullDistanceCache = new HashMap<DistanceStyle,Double>();
+    /** Normalized plane connecting the two points and going through world center */
+    public final Plane normalizedConnectingPlane;
+    /** Cutoff plane parallel to connecting plane representing one side of the path segment */
+    public final SidedPlane upperConnectingPlane;
+    /** Cutoff plane parallel to connecting plane representing the other side of the path segment */
+    public final SidedPlane lowerConnectingPlane;
+    /** Plane going through the center and start point, marking the start edge of the segment */
+    public final SidedPlane startCutoffPlane;
+    /** Plane going through the center and end point, marking the end edge of the segment */
+    public final SidedPlane endCutoffPlane;
+    /** Upper right hand corner of segment */
+    public final GeoPoint URHC;
+    /** Lower right hand corner of segment */
+    public final GeoPoint LRHC;
+    /** Upper left hand corner of segment */
+    public final GeoPoint ULHC;
+    /** Lower left hand corner of segment */
+    public final GeoPoint LLHC;
+    /** Notable points for the upper connecting plane */
+    public final GeoPoint[] upperConnectingPlanePoints;
+    /** Notable points for the lower connecting plane */
+    public final GeoPoint[] lowerConnectingPlanePoints;
+    /** Notable points for the start cutoff plane */
+    public final GeoPoint[] startCutoffPlanePoints;
+    /** Notable points for the end cutoff plane */
+    public final GeoPoint[] endCutoffPlanePoints;
+
+    /** Construct a path segment.
+     *@param planetModel is the planet model.
+     *@param start is the starting point.
+     *@param end is the ending point.
+     *@param normalizedConnectingPlane is the connecting plane.
+     *@param planeBoundingOffset is the linear offset from the connecting plane to either side.
+     */
+    public PathSegment(final PlanetModel planetModel, final GeoPoint start, final GeoPoint end,
+      final Plane normalizedConnectingPlane, final double planeBoundingOffset) {
+      this.start = start;
+      this.end = end;
+      this.normalizedConnectingPlane = normalizedConnectingPlane;
+        
+      // Either start or end should be on the correct side
+      upperConnectingPlane = new SidedPlane(start, normalizedConnectingPlane, -planeBoundingOffset);
+      lowerConnectingPlane = new SidedPlane(start, normalizedConnectingPlane, planeBoundingOffset);
+      // Cutoff planes use opposite endpoints as correct side examples
+      startCutoffPlane = new SidedPlane(end, normalizedConnectingPlane, start);
+      endCutoffPlane = new SidedPlane(start, normalizedConnectingPlane, end);
+      final Membership[] upperSide = new Membership[]{upperConnectingPlane};
+      final Membership[] lowerSide = new Membership[]{lowerConnectingPlane};
+      final Membership[] startSide = new Membership[]{startCutoffPlane};
+      final Membership[] endSide = new Membership[]{endCutoffPlane};
+      GeoPoint[] points;
+      points = upperConnectingPlane.findIntersections(planetModel, startCutoffPlane, lowerSide, endSide);
+      if (points.length == 0) {
+        throw new IllegalArgumentException("Some segment boundary points are off the ellipsoid; path too wide");
+      }
+      this.ULHC = points[0];
+      points = upperConnectingPlane.findIntersections(planetModel, endCutoffPlane, lowerSide, startSide);
+      if (points.length == 0) {
+        throw new IllegalArgumentException("Some segment boundary points are off the ellipsoid; path too wide");
+      }
+      this.URHC = points[0];
+      points = lowerConnectingPlane.findIntersections(planetModel, startCutoffPlane, upperSide, endSide);
+      if (points.length == 0) {
+        throw new IllegalArgumentException("Some segment boundary points are off the ellipsoid; path too wide");
+      }
+      this.LLHC = points[0];
+      points = lowerConnectingPlane.findIntersections(planetModel, endCutoffPlane, upperSide, startSide);
+      if (points.length == 0) {
+        throw new IllegalArgumentException("Some segment boundary points are off the ellipsoid; path too wide");
+      }
+      this.LRHC = points[0];
+      upperConnectingPlanePoints = new GeoPoint[]{ULHC, URHC};
+      lowerConnectingPlanePoints = new GeoPoint[]{LLHC, LRHC};
+      startCutoffPlanePoints = new GeoPoint[]{ULHC, LLHC};
+      endCutoffPlanePoints = new GeoPoint[]{URHC, LRHC};
+    }
+
+    /** Compute the full distance along this path segment.
+     *@param distanceStyle is the distance style.
+     *@return the distance metric.
+     */
+    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();
+      }
+    }
+  
+    /** Check if point is within this segment.
+     *@param point is the point.
+     *@return true of within.
+     */
+    public boolean isWithin(final Vector point) {
+      return startCutoffPlane.isWithin(point) &&
+          endCutoffPlane.isWithin(point) &&
+          upperConnectingPlane.isWithin(point) &&
+          lowerConnectingPlane.isWithin(point);
+    }
+
+    /** Check if point is within this segment.
+     *@param x is the point x.
+     *@param y is the point y.
+     *@param z is the point z.
+     *@return true of within.
+     */
+    public boolean isWithin(final double x, final double y, final double z) {
+      return startCutoffPlane.isWithin(x, y, z) &&
+          endCutoffPlane.isWithin(x, y, z) &&
+          upperConnectingPlane.isWithin(x, y, z) &&
+          lowerConnectingPlane.isWithin(x, y, z);
+    }
+
+    /** Compute interior path distance.
+     *@param planetModel is the planet model.
+     *@param distanceStyle is the distance style.
+     *@param x is the point x.
+     *@param y is the point y.
+     *@param z is the point z.
+     *@return the distance metric.
+     */
+    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;
+
+      // (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 * 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);
+    }
+
+    /** Compute external distance.
+     *@param planetModel is the planet model.
+     *@param distanceStyle is the distance style.
+     *@param x is the point x.
+     *@param y is the point y.
+     *@param z is the point z.
+     *@return the distance metric.
+     */
+    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)));
+    }
+
+    /** Determine if this endpoint intersects a specified plane.
+     *@param planetModel is the planet model.
+     *@param p is the plane.
+     *@param notablePoints are the points associated with the plane.
+     *@param bounds are any bounds which the intersection must lie within.
+     *@return true if there is a matching intersection.
+     */
+    public boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
+      return upperConnectingPlane.intersects(planetModel, p, notablePoints, upperConnectingPlanePoints, bounds, lowerConnectingPlane, startCutoffPlane, endCutoffPlane) ||
+          lowerConnectingPlane.intersects(planetModel, p, notablePoints, lowerConnectingPlanePoints, bounds, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
+    }
+
+    /** Get the bounds for a segment endpoint.
+     *@param planetModel is the planet model.
+     *@param bounds are the bounds to be modified.
+     */
+    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).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);
+    }
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPoint.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPoint.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPoint.java
new file mode 100755
index 0000000..31ab0aa
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPoint.java
@@ -0,0 +1,193 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+    
+/**
+ * This class represents a point on the surface of a sphere or ellipsoid.
+ *
+ * @lucene.experimental
+ */
+public class GeoPoint extends Vector {
+  
+  // By making lazily-evaluated variables be "volatile", we guarantee atomicity when they
+  // are updated.  This is necessary if we are using these classes in a multi-thread fashion,
+  // because we don't try to synchronize for the lazy computation.
+  
+  /** This is the lazily-evaluated magnitude.  Some constructors include it, but others don't, and
+   * we try not to create extra computation by always computing it.  Does not need to be
+   * synchronized for thread safety, because depends wholly on immutable variables of this class. */
+  protected volatile double magnitude = Double.NEGATIVE_INFINITY;
+  /** Lazily-evaluated latitude.  Does not need to be
+   * synchronized for thread safety, because depends wholly on immutable variables of this class.  */
+  protected volatile double latitude = Double.NEGATIVE_INFINITY;
+  /** Lazily-evaluated longitude.   Does not need to be
+   * synchronized for thread safety, because depends wholly on immutable variables of this class.  */
+  protected volatile double longitude = Double.NEGATIVE_INFINITY;
+
+  /** Construct a GeoPoint from the trig functions of a lat and lon pair.
+   * @param planetModel is the planetModel to put the point on.
+   * @param sinLat is the sin of the latitude.
+   * @param sinLon is the sin of the longitude.
+   * @param cosLat is the cos of the latitude.
+   * @param cosLon is the cos of the longitude.
+   * @param lat is the latitude.
+   * @param lon is the longitude.
+   */
+  public GeoPoint(final PlanetModel planetModel, final double sinLat, final double sinLon, final double cosLat, final double cosLon, final double lat, final double lon) {
+    this(computeDesiredEllipsoidMagnitude(planetModel, cosLat * cosLon, cosLat * sinLon, sinLat),
+      cosLat * cosLon, cosLat * sinLon, sinLat, lat, lon);
+  }
+  
+  /** Construct a GeoPoint from the trig functions of a lat and lon pair.
+   * @param planetModel is the planetModel to put the point on.
+   * @param sinLat is the sin of the latitude.
+   * @param sinLon is the sin of the longitude.
+   * @param cosLat is the cos of the latitude.
+   * @param cosLon is the cos of the longitude.
+   */
+  public GeoPoint(final PlanetModel planetModel, final double sinLat, final double sinLon, final double cosLat, final double cosLon) {
+    this(computeDesiredEllipsoidMagnitude(planetModel, cosLat * cosLon, cosLat * sinLon, sinLat),
+      cosLat * cosLon, cosLat * sinLon, sinLat);
+  }
+
+  /** Construct a GeoPoint from a latitude/longitude pair.
+   * @param planetModel is the planetModel to put the point on.
+   * @param lat is the latitude.
+   * @param lon is the longitude.
+   */
+  public GeoPoint(final PlanetModel planetModel, final double lat, final double lon) {
+    this(planetModel, Math.sin(lat), Math.sin(lon), Math.cos(lat), Math.cos(lon), lat, lon);
+  }
+  
+  /** Construct a GeoPoint from a unit (x,y,z) vector and a magnitude.
+   * @param magnitude is the desired magnitude, provided to put the point on the ellipsoid.
+   * @param x is the unit x value.
+   * @param y is the unit y value.
+   * @param z is the unit z value.
+   * @param lat is the latitude.
+   * @param lon is the longitude.
+   */
+  public GeoPoint(final double magnitude, final double x, final double y, final double z, double lat, double lon) {
+    super(x * magnitude, y * magnitude, z * magnitude);
+    this.magnitude = magnitude;
+    if (lat > Math.PI * 0.5 || lat < -Math.PI * 0.5) {
+      throw new IllegalArgumentException("Latitude " + lat + " is out of range: must range from -Math.PI/2 to Math.PI/2");
+    }
+    if (lon < -Math.PI || lon > Math.PI) {
+      throw new IllegalArgumentException("Longitude " + lon + " is out of range: must range from -Math.PI to Math.PI");
+    }
+    this.latitude = lat;
+    this.longitude = lon;
+  }
+
+  /** Construct a GeoPoint from a unit (x,y,z) vector and a magnitude.
+   * @param magnitude is the desired magnitude, provided to put the point on the ellipsoid.
+   * @param x is the unit x value.
+   * @param y is the unit y value.
+   * @param z is the unit z value.
+   */
+  public GeoPoint(final double magnitude, final double x, final double y, final double z) {
+    super(x * magnitude, y * magnitude, z * magnitude);
+    this.magnitude = magnitude;
+  }
+  
+  /** Construct a GeoPoint from an (x,y,z) value.
+   * The (x,y,z) tuple must be on the desired ellipsoid.
+   * @param x is the ellipsoid point x value.
+   * @param y is the ellipsoid point y value.
+   * @param z is the ellipsoid point z value.
+   */
+  public GeoPoint(final double x, final double y, final double z) {
+    super(x, y, z);
+  }
+
+  /** Compute an arc distance between two points.
+   * Note: this is an angular distance, and not a surface distance, and is therefore independent of planet model.
+   * For surface distance, see {@link PlanetModel#surfaceDistance(GeoPoint, GeoPoint)}
+   * @param v is the second point.
+   * @return the angle, in radians, between the two points.
+   */
+  public double arcDistance(final GeoPoint v) {
+    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.
+   */
+  public double getLatitude() {
+    double lat = this.latitude;//volatile-read once
+    if (lat == Double.NEGATIVE_INFINITY)
+      this.latitude = lat = Math.asin(z / magnitude());
+    return lat;
+  }
+  
+  /** Compute the longitude for the point.
+   * @return the longitude value.  Uses 0.0 if there is no computable longitude.
+   */
+  public double getLongitude() {
+    double lon = this.longitude;//volatile-read once
+    if (lon == Double.NEGATIVE_INFINITY) {
+      if (Math.abs(x) < MINIMUM_RESOLUTION && Math.abs(y) < MINIMUM_RESOLUTION)
+        this.longitude = lon = 0.0;
+      else
+        this.longitude = lon = Math.atan2(y,x);
+    }
+    return lon;
+  }
+  
+  /** Compute the linear magnitude of the point.
+   * @return the magnitude.
+   */
+  @Override
+  public double magnitude() {
+    double mag = this.magnitude;//volatile-read once
+    if (mag == Double.NEGATIVE_INFINITY) {
+      this.magnitude = mag = super.magnitude();
+    }
+    return mag;
+  }
+  
+  /** Compute whether point matches another.
+   *@param x is the x value
+   *@param y is the y value
+   *@param z is the z value
+   *@return true if the same.
+   */
+  public boolean isIdentical(final double x, final double y, final double z) {
+    return Math.abs(this.x - x) < MINIMUM_RESOLUTION &&
+      Math.abs(this.y - y) < MINIMUM_RESOLUTION &&
+      Math.abs(this.z - z) < MINIMUM_RESOLUTION;
+  }
+  
+  @Override
+  public String toString() {
+    if (this.longitude == Double.NEGATIVE_INFINITY) {
+      return super.toString();
+    }
+    return "[lat="+getLatitude()+", lon="+getLongitude()+"]";
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPolygon.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPolygon.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPolygon.java
new file mode 100644
index 0000000..742bdf8
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPolygon.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * GeoPolygon interface description.
+ *
+ * @lucene.experimental
+ */
+public interface GeoPolygon extends GeoMembershipShape {
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPolygonFactory.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPolygonFactory.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPolygonFactory.java
new file mode 100755
index 0000000..8ee4290
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoPolygonFactory.java
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+
+/**
+ * Class which constructs a GeoMembershipShape representing an arbitrary polygon.
+ *
+ * @lucene.experimental
+ */
+public class GeoPolygonFactory {
+  private GeoPolygonFactory() {
+  }
+
+  /**
+   * Create a GeoMembershipShape of the right kind given the specified bounds.
+   *
+   * @param pointList        is a list of the GeoPoints to build an arbitrary polygon out of.
+   * @param convexPointIndex is the index of a single convex point whose conformation with
+   *                         its neighbors determines inside/outside for the entire polygon.
+   * @return a GeoPolygon corresponding to what was specified.
+   */
+  public static GeoPolygon makeGeoPolygon(final PlanetModel planetModel, final List<GeoPoint> pointList, final int convexPointIndex) {
+    // The basic operation uses a set of points, two points determining one particular edge, and a sided plane
+    // describing membership.
+    return buildPolygonShape(planetModel, pointList, convexPointIndex, getLegalIndex(convexPointIndex + 1, pointList.size()),
+        new SidedPlane(pointList.get(getLegalIndex(convexPointIndex - 1, pointList.size())),
+            pointList.get(convexPointIndex), pointList.get(getLegalIndex(convexPointIndex + 1, pointList.size()))),
+        false);
+  }
+
+  /** Build a GeoMembershipShape given points, starting edge, and whether starting edge is internal or not.
+   * @param pointsList        is a list of the GeoPoints to build an arbitrary polygon out of.
+   * @param startPointIndex is one of the points constituting the starting edge.
+   * @param endPointIndex is another of the points constituting the starting edge.
+   * @param startingEdge is the plane describing the starting edge.
+   * @param isInternalEdge is true if the specified edge is an internal one.
+   * @return a GeoMembershipShape corresponding to what was specified.
+   */
+  public static GeoPolygon buildPolygonShape(final PlanetModel planetModel, final List<GeoPoint> pointsList, final int startPointIndex, final int endPointIndex, final SidedPlane startingEdge, final boolean isInternalEdge) {
+    // Algorithm as follows:
+    // Start with sided edge.  Go through all points in some order.  For each new point, determine if the point is within all edges considered so far.
+    // If not, put it into a list of points for recursion.  If it is within, add new edge and keep going.
+    // Once we detect a point that is within, if there are points put aside for recursion, then call recursively.
+
+    // Current composite.  This is what we'll actually be returning.
+    final GeoCompositePolygon rval = new GeoCompositePolygon();
+
+    final List<GeoPoint> recursionList = new ArrayList<GeoPoint>();
+    final List<GeoPoint> currentList = new ArrayList<GeoPoint>();
+    final BitSet internalEdgeList = new BitSet();
+    final List<SidedPlane> currentPlanes = new ArrayList<SidedPlane>();
+
+    // Initialize the current list and current planes
+    currentList.add(pointsList.get(startPointIndex));
+    currentList.add(pointsList.get(endPointIndex));
+    internalEdgeList.set(currentPlanes.size(), isInternalEdge);
+    currentPlanes.add(startingEdge);
+
+    // Now, scan all remaining points, in order.  We'll use an index and just add to it.
+    for (int i = 0; i < pointsList.size() - 2; i++) {
+      GeoPoint newPoint = pointsList.get(getLegalIndex(i + endPointIndex + 1, pointsList.size()));
+      if (isWithin(newPoint, currentPlanes)) {
+        // Construct a sided plane based on the last two points, and the previous point
+        SidedPlane newBoundary = new SidedPlane(currentList.get(currentList.size() - 2), newPoint, currentList.get(currentList.size() - 1));
+        // Construct a sided plane based on the return trip
+        SidedPlane returnBoundary = new SidedPlane(currentList.get(currentList.size() - 1), currentList.get(0), newPoint);
+        // Verify that none of the points beyond the new point in the list are inside the polygon we'd
+        // be creating if we stopped making the current polygon right now.
+        boolean pointInside = false;
+        for (int j = i + 1; j < pointsList.size() - 2; j++) {
+          GeoPoint checkPoint = pointsList.get(getLegalIndex(j + endPointIndex + 1, pointsList.size()));
+          boolean isInside = true;
+          if (isInside && !newBoundary.isWithin(checkPoint))
+            isInside = false;
+          if (isInside && !returnBoundary.isWithin(checkPoint))
+            isInside = false;
+          if (isInside) {
+            for (SidedPlane plane : currentPlanes) {
+              if (!plane.isWithin(checkPoint)) {
+                isInside = false;
+                break;
+              }
+            }
+          }
+          if (isInside) {
+            pointInside = true;
+            break;
+          }
+        }
+        if (!pointInside) {
+          // Any excluded points?
+          boolean isInternalBoundary = recursionList.size() > 0;
+          if (isInternalBoundary) {
+            // Handle exclusion
+            recursionList.add(newPoint);
+            recursionList.add(currentList.get(currentList.size() - 1));
+            if (recursionList.size() == pointsList.size()) {
+              // We are trying to recurse with a list the same size as the one we started with.
+              // Clearly, the polygon cannot be constructed
+              throw new IllegalArgumentException("Polygon is illegal; cannot be decomposed into convex parts");
+            }
+            // We want the other side for the recursion
+            SidedPlane otherSideNewBoundary = new SidedPlane(newBoundary);
+            rval.addShape(buildPolygonShape(planetModel, recursionList, recursionList.size() - 2, recursionList.size() - 1, otherSideNewBoundary, true));
+            recursionList.clear();
+          }
+          currentList.add(newPoint);
+          internalEdgeList.set(currentPlanes.size(), isInternalBoundary);
+          currentPlanes.add(newBoundary);
+        } else {
+          recursionList.add(newPoint);
+        }
+      } else {
+        recursionList.add(newPoint);
+      }
+    }
+
+    boolean returnEdgeInternalBoundary = recursionList.size() > 0;
+    if (returnEdgeInternalBoundary) {
+      // The last step back to the start point had a recursion, so take care of that before we complete our work
+      recursionList.add(currentList.get(0));
+      recursionList.add(currentList.get(currentList.size() - 1));
+      if (recursionList.size() == pointsList.size()) {
+        // We are trying to recurse with a list the same size as the one we started with.
+        // Clearly, the polygon cannot be constructed
+        throw new IllegalArgumentException("Polygon is illegal; cannot be decomposed into convex parts");
+      }
+      // Construct a sided plane based on these two points, and the previous point
+      SidedPlane newBoundary = new SidedPlane(currentList.get(currentList.size() - 2), currentList.get(0), currentList.get(currentList.size() - 1));
+      // We want the other side for the recursion
+      SidedPlane otherSideNewBoundary = new SidedPlane(newBoundary);
+      rval.addShape(buildPolygonShape(planetModel, recursionList, recursionList.size() - 2, recursionList.size() - 1, otherSideNewBoundary, true));
+      recursionList.clear();
+    }
+    // Now, add in the current shape.
+    rval.addShape(new GeoConvexPolygon(planetModel, currentList, internalEdgeList, returnEdgeInternalBoundary));
+    //System.out.println("Done creating polygon");
+    return rval;
+  }
+
+  /** Check if a point is within a described list of planes.
+   *@param newPoint is the point. 
+   *@param currentPlanes is the list of planes.
+   *@return true if within.
+   */
+  protected static boolean isWithin(final GeoPoint newPoint, final List<SidedPlane> currentPlanes) {
+    for (SidedPlane p : currentPlanes) {
+      if (!p.isWithin(newPoint))
+        return false;
+    }
+    return true;
+  }
+
+  /** Convert raw point index into valid array position.
+   *@param index is the array index.
+   *@param size is the array size.
+   *@return an updated index.
+   */
+  protected static int getLegalIndex(int index, int size) {
+    while (index < 0) {
+      index += size;
+    }
+    while (index >= size) {
+      index -= size;
+    }
+    return index;
+  }
+
+}


[33/50] [abbrv] lucene-solr git commit: LUCENE-7075: remove legacy numericutils usage from test.

Posted by no...@apache.org.
LUCENE-7075: remove legacy numericutils usage from test.


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

Branch: refs/heads/apiv2
Commit: 4cc9ad44df9ce26aadcb8d9ef739e303d32d6db6
Parents: dd1dd46
Author: Robert Muir <rm...@apache.org>
Authored: Tue Mar 8 08:40:39 2016 -0500
Committer: Robert Muir <rm...@apache.org>
Committed: Tue Mar 8 08:41:24 2016 -0500

----------------------------------------------------------------------
 .../lucene/search/join/TestBlockJoin.java       | 72 +++++++++++---------
 .../java/org/apache/lucene/util/TestUtil.java   | 23 -------
 2 files changed, 38 insertions(+), 57 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4cc9ad44/lucene/join/src/test/org/apache/lucene/search/join/TestBlockJoin.java
----------------------------------------------------------------------
diff --git a/lucene/join/src/test/org/apache/lucene/search/join/TestBlockJoin.java b/lucene/join/src/test/org/apache/lucene/search/join/TestBlockJoin.java
index a198774..b5f2038 100644
--- a/lucene/join/src/test/org/apache/lucene/search/join/TestBlockJoin.java
+++ b/lucene/join/src/test/org/apache/lucene/search/join/TestBlockJoin.java
@@ -26,8 +26,8 @@ import java.util.Locale;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.IntPoint;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.LegacyIntField;
 import org.apache.lucene.document.NumericDocValuesField;
 import org.apache.lucene.document.SortedDocValuesField;
 import org.apache.lucene.document.StoredField;
@@ -52,10 +52,8 @@ import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.FieldDoc;
 import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.LegacyNumericRangeQuery;
 import org.apache.lucene.search.MatchAllDocsQuery;
 import org.apache.lucene.search.MatchNoDocsQuery;
-import org.apache.lucene.search.MultiTermQuery;
 import org.apache.lucene.search.PrefixQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.QueryUtils;
@@ -73,8 +71,6 @@ import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.BitSet;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.BytesRefBuilder;
-import org.apache.lucene.util.LegacyNumericUtils;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
 
@@ -93,7 +89,7 @@ public class TestBlockJoin extends LuceneTestCase {
   private Document makeJob(String skill, int year) {
     Document job = new Document();
     job.add(newStringField("skill", skill, Field.Store.YES));
-    job.add(new LegacyIntField("year", year, Field.Store.NO));
+    job.add(new IntPoint("year", year));
     job.add(new StoredField("year", year));
     return job;
   }
@@ -102,7 +98,7 @@ public class TestBlockJoin extends LuceneTestCase {
   private Document makeQualification(String qualification, int year) {
     Document job = new Document();
     job.add(newStringField("qualification", qualification, Field.Store.YES));
-    job.add(new LegacyIntField("year", year, Field.Store.NO));
+    job.add(new IntPoint("year", year));
     return job;
   }
   
@@ -135,7 +131,7 @@ public class TestBlockJoin extends LuceneTestCase {
 
     BooleanQuery.Builder childQuery = new BooleanQuery.Builder();
     childQuery.add(new BooleanClause(new TermQuery(new Term("skill", "java")), Occur.MUST));
-    childQuery.add(new BooleanClause(LegacyNumericRangeQuery.newIntRange("year", 2006, 2011, true, true), Occur.MUST));
+    childQuery.add(new BooleanClause(IntPoint.newRangeQuery("year", 2006, 2011), Occur.MUST));
 
     ToParentBlockJoinQuery childJoinQuery = new ToParentBlockJoinQuery(childQuery.build(), parentsFilter, ScoreMode.Avg);
 
@@ -189,7 +185,7 @@ public class TestBlockJoin extends LuceneTestCase {
     // Define child document criteria (finds an example of relevant work experience)
     BooleanQuery.Builder childQuery = new BooleanQuery.Builder();
     childQuery.add(new BooleanClause(new TermQuery(new Term("skill", "java")), Occur.MUST));
-    childQuery.add(new BooleanClause(LegacyNumericRangeQuery.newIntRange("year", 2006, 2011, true, true), Occur.MUST));
+    childQuery.add(new BooleanClause(IntPoint.newRangeQuery("year", 2006, 2011), Occur.MUST));
 
     // Define parent document criteria (find a resident in the UK)
     Query parentQuery = new TermQuery(new Term("country", "United Kingdom"));
@@ -269,23 +265,30 @@ public class TestBlockJoin extends LuceneTestCase {
     w.close();
     IndexSearcher s = newSearcher(r);
 
-    MultiTermQuery qc = LegacyNumericRangeQuery.newIntRange("year", 2007, 2007, true, true);
     // Hacky: this causes the query to need 2 rewrite
     // iterations: 
-    qc.setRewriteMethod(MultiTermQuery.CONSTANT_SCORE_BOOLEAN_REWRITE);
+    BooleanQuery.Builder builder = new BooleanQuery.Builder();
+    builder.add(IntPoint.newExactQuery("year", 2007), BooleanClause.Occur.MUST);
+    Query qc = new Query() {
+      @Override
+      public Query rewrite(IndexReader reader) throws IOException {
+        return builder.build();
+      }
+
+      @Override
+      public String toString(String field) {
+        return "hack!";
+      }
+    };
 
     BitSetProducer parentsFilter = new QueryBitSetProducer(new TermQuery(new Term("docType", "resume")));
     CheckJoinIndex.check(r, parentsFilter);
 
-    int h1 = qc.hashCode();
     Query qw1 = qc.rewrite(r);
-    int h2 = qw1.hashCode();
     Query qw2 = qw1.rewrite(r);
-    int h3 = qw2.hashCode();
 
-    assertTrue(h1 != h2);
-    assertTrue(h2 != h3);
-    assertTrue(h3 != h1);
+    assertNotSame(qc, qw1);
+    assertNotSame(qw1, qw2);
 
     ToParentBlockJoinQuery qp = new ToParentBlockJoinQuery(qc, parentsFilter, ScoreMode.Max);
     ToParentBlockJoinCollector c = new ToParentBlockJoinCollector(Sort.RELEVANCE, 10, true, true);
@@ -342,7 +345,7 @@ public class TestBlockJoin extends LuceneTestCase {
     // Define child document criteria (finds an example of relevant work experience)
     BooleanQuery.Builder childQuery = new BooleanQuery.Builder();
     childQuery.add(new BooleanClause(new TermQuery(new Term("skill", "java")), Occur.MUST));
-    childQuery.add(new BooleanClause(LegacyNumericRangeQuery.newIntRange("year", 2006, 2011, true, true), Occur.MUST));
+    childQuery.add(new BooleanClause(IntPoint.newRangeQuery("year", 2006, 2011), Occur.MUST));
 
     // Define parent document criteria (find a resident in the UK)
     Query parentQuery = new TermQuery(new Term("country", "United Kingdom"));
@@ -516,7 +519,7 @@ public class TestBlockJoin extends LuceneTestCase {
     for(int parentDocID=0;parentDocID<numParentDocs;parentDocID++) {
       Document parentDoc = new Document();
       Document parentJoinDoc = new Document();
-      Field id = new LegacyIntField("parentID", parentDocID, Field.Store.YES);
+      Field id = new StoredField("parentID", parentDocID);
       parentDoc.add(id);
       parentJoinDoc.add(id);
       parentJoinDoc.add(newStringField("isParent", "x", Field.Store.NO));
@@ -538,8 +541,8 @@ public class TestBlockJoin extends LuceneTestCase {
       }
 
       if (doDeletes) {
-        parentDoc.add(new LegacyIntField("blockID", parentDocID, Field.Store.NO));
-        parentJoinDoc.add(new LegacyIntField("blockID", parentDocID, Field.Store.NO));
+        parentDoc.add(new IntPoint("blockID", parentDocID));
+        parentJoinDoc.add(new IntPoint("blockID", parentDocID));
       }
 
       final List<Document> joinDocs = new ArrayList<>();
@@ -563,7 +566,7 @@ public class TestBlockJoin extends LuceneTestCase {
         Document joinChildDoc = new Document();
         joinDocs.add(joinChildDoc);
 
-        Field childID = new LegacyIntField("childID", childDocID, Field.Store.YES);
+        Field childID = new StoredField("childID", childDocID);
         childDoc.add(childID);
         joinChildDoc.add(childID);
         childID = new NumericDocValuesField("childID", childDocID);
@@ -596,7 +599,7 @@ public class TestBlockJoin extends LuceneTestCase {
         }
 
         if (doDeletes) {
-          joinChildDoc.add(new LegacyIntField("blockID", parentDocID, Field.Store.NO));
+          joinChildDoc.add(new IntPoint("blockID", parentDocID));
         }
 
         w.addDocument(childDoc);
@@ -611,14 +614,15 @@ public class TestBlockJoin extends LuceneTestCase {
       }
     }
 
-    BytesRefBuilder term = new BytesRefBuilder();
-    for(int deleteID : toDelete) {
-      if (VERBOSE) {
-        System.out.println("DELETE parentID=" + deleteID);
+    if (!toDelete.isEmpty()) {
+      // TODO: we should add newSetQuery(String, Collection<T>) ? this is awkward.
+      int[] array = new int[toDelete.size()];
+      for (int i = 0; i < toDelete.size(); i++) {
+        array[i] = toDelete.get(i);
       }
-      LegacyNumericUtils.intToPrefixCoded(deleteID, 0, term);
-      w.deleteDocuments(new Term("blockID", term.toBytesRef()));
-      joinW.deleteDocuments(new Term("blockID", term.toBytesRef()));
+      Query query = IntPoint.newSetQuery("blockID", array);
+      w.deleteDocuments(query);
+      joinW.deleteDocuments(query);
     }
 
     final IndexReader r = w.getReader();
@@ -1061,11 +1065,11 @@ public class TestBlockJoin extends LuceneTestCase {
     // Define child document criteria (finds an example of relevant work experience)
     BooleanQuery.Builder childJobQuery = new BooleanQuery.Builder();
     childJobQuery.add(new BooleanClause(new TermQuery(new Term("skill", "java")), Occur.MUST));
-    childJobQuery.add(new BooleanClause(LegacyNumericRangeQuery.newIntRange("year", 2006, 2011, true, true), Occur.MUST));
+    childJobQuery.add(new BooleanClause(IntPoint.newRangeQuery("year", 2006, 2011), Occur.MUST));
 
     BooleanQuery.Builder childQualificationQuery = new BooleanQuery.Builder();
     childQualificationQuery.add(new BooleanClause(new TermQuery(new Term("qualification", "maths")), Occur.MUST));
-    childQualificationQuery.add(new BooleanClause(LegacyNumericRangeQuery.newIntRange("year", 1980, 2000, true, true), Occur.MUST));
+    childQualificationQuery.add(new BooleanClause(IntPoint.newRangeQuery("year", 1980, 2000), Occur.MUST));
 
 
     // Define parent document criteria (find a resident in the UK)
@@ -1210,7 +1214,7 @@ public class TestBlockJoin extends LuceneTestCase {
     // Define child document criteria (finds an example of relevant work experience)
     BooleanQuery.Builder childQuery = new BooleanQuery.Builder();
     childQuery.add(new BooleanClause(new TermQuery(new Term("skill", "java")), Occur.MUST));
-    childQuery.add(new BooleanClause(LegacyNumericRangeQuery.newIntRange("year", 2006, 2011, true, true), Occur.MUST));
+    childQuery.add(new BooleanClause(IntPoint.newRangeQuery("year", 2006, 2011), Occur.MUST));
 
     // Wrap the child document query to 'join' any matches
     // up to corresponding parent:
@@ -1707,7 +1711,7 @@ public class TestBlockJoin extends LuceneTestCase {
       Query resumeQuery = new ToChildBlockJoinQuery(new TermQuery(new Term("country","rv" + qrv)),
                                                     resumeFilter);
       
-      Query jobQuery = new ToChildBlockJoinQuery(LegacyNumericRangeQuery.newIntRange("year", qjv, qjv, true, true),
+      Query jobQuery = new ToChildBlockJoinQuery(IntPoint.newRangeQuery("year", qjv, qjv),
                                                  jobFilter);
       
       BooleanQuery.Builder fullQuery = new BooleanQuery.Builder();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4cc9ad44/lucene/test-framework/src/java/org/apache/lucene/util/TestUtil.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/util/TestUtil.java b/lucene/test-framework/src/java/org/apache/lucene/util/TestUtil.java
index 50692e8..5e328ba 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/util/TestUtil.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/util/TestUtil.java
@@ -61,11 +61,6 @@ import org.apache.lucene.document.BinaryDocValuesField;
 import org.apache.lucene.document.BinaryPoint;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.FieldType.LegacyNumericType;
-import org.apache.lucene.document.LegacyDoubleField;
-import org.apache.lucene.document.LegacyFloatField;
-import org.apache.lucene.document.LegacyIntField;
-import org.apache.lucene.document.LegacyLongField;
 import org.apache.lucene.document.NumericDocValuesField;
 import org.apache.lucene.document.SortedDocValuesField;
 import org.apache.lucene.index.CheckIndex;
@@ -1072,7 +1067,6 @@ public final class TestUtil {
       final Field field2;
       final DocValuesType dvType = field1.fieldType().docValuesType();
       final int dimCount = field1.fieldType().pointDimensionCount();
-      final LegacyNumericType numType = field1.fieldType().numericType();
       if (dvType != DocValuesType.NONE) {
         switch(dvType) {
           case NUMERIC:
@@ -1092,23 +1086,6 @@ public final class TestUtil {
         byte[] bytes = new byte[br.length];
         System.arraycopy(br.bytes, br.offset, bytes, 0, br.length);
         field2 = new BinaryPoint(field1.name(), bytes, field1.fieldType());
-      } else if (numType != null) {
-        switch (numType) {
-          case INT:
-            field2 = new LegacyIntField(field1.name(), field1.numericValue().intValue(), field1.fieldType());
-            break;
-          case FLOAT:
-            field2 = new LegacyFloatField(field1.name(), field1.numericValue().intValue(), field1.fieldType());
-            break;
-          case LONG:
-            field2 = new LegacyLongField(field1.name(), field1.numericValue().intValue(), field1.fieldType());
-            break;
-          case DOUBLE:
-            field2 = new LegacyDoubleField(field1.name(), field1.numericValue().intValue(), field1.fieldType());
-            break;
-          default:
-            throw new IllegalStateException("unknown Type: " + numType);
-        }
       } else {
         field2 = new Field(field1.name(), field1.stringValue(), field1.fieldType());
       }


[19/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LinearDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LinearDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LinearDistance.java
deleted file mode 100644
index 9cbedba..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LinearDistance.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Linear distance computation style.
- *
- * @lucene.experimental
- */
-public class LinearDistance implements DistanceStyle {
-  
-  /** A convenient instance */
-  public final static LinearDistance INSTANCE = new LinearDistance();
-  
-  /** Constructor.
-   */
-  public LinearDistance() {
-  }
-  
-  @Override
-  public double computeDistance(final GeoPoint point1, final GeoPoint point2) {
-    return point1.linearDistance(point2);
-  }
-  
-  @Override
-  public double computeDistance(final GeoPoint point1, final double x2, final double y2, final double z2) {
-    return point1.linearDistance(x2,y2,z2);
-  }
-
-  @Override
-  public double computeDistance(final PlanetModel planetModel, final Plane plane, final GeoPoint point, final Membership... bounds) {
-    return plane.linearDistance(planetModel, point, bounds);
-  }
-  
-  @Override
-  public double computeDistance(final PlanetModel planetModel, final Plane plane, final double x, final double y, final double z, final Membership... bounds) {
-    return plane.linearDistance(planetModel, x,y,z, bounds);
-  }
-
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LinearSquaredDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LinearSquaredDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LinearSquaredDistance.java
deleted file mode 100644
index 028d3c4..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LinearSquaredDistance.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Linear squared distance computation style.
- *
- * @lucene.experimental
- */
-public class LinearSquaredDistance implements DistanceStyle {
-  
-  /** A convenient instance */
-  public final static LinearSquaredDistance INSTANCE = new LinearSquaredDistance();
-  
-  /** Constructor.
-   */
-  public LinearSquaredDistance() {
-  }
-  
-  @Override
-  public double computeDistance(final GeoPoint point1, final GeoPoint point2) {
-    return point1.linearDistanceSquared(point2);
-  }
-  
-  @Override
-  public double computeDistance(final GeoPoint point1, final double x2, final double y2, final double z2) {
-    return point1.linearDistanceSquared(x2,y2,z2);
-  }
-
-  @Override
-  public double computeDistance(final PlanetModel planetModel, final Plane plane, final GeoPoint point, final Membership... bounds) {
-    return plane.linearDistanceSquared(planetModel, point, bounds);
-  }
-  
-  @Override
-  public double computeDistance(final PlanetModel planetModel, final Plane plane, final double x, final double y, final double z, final Membership... bounds) {
-    return plane.linearDistanceSquared(planetModel, x,y,z, bounds);
-  }
-
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Membership.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Membership.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Membership.java
deleted file mode 100755
index 3ca6b09..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Membership.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Implemented by Geo3D shapes that can calculate if a point is within it or not.
- *
- * @lucene.experimental
- */
-public interface Membership {
-
-  /**
-   * Check if a point is within this shape.
-   *
-   * @param point is the point to check.
-   * @return true if the point is within this shape
-   */
-  public default 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
-   */
-  public boolean isWithin(final double x, final double y, final double z);
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/NormalDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/NormalDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/NormalDistance.java
deleted file mode 100644
index cdac0d2..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/NormalDistance.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Normal distance computation style.
- *
- * @lucene.experimental
- */
-public class NormalDistance implements DistanceStyle {
-  
-  /** A convenient instance */
-  public final static NormalDistance INSTANCE = new NormalDistance();
-  
-  /** Constructor.
-   */
-  public NormalDistance() {
-  }
-  
-  @Override
-  public double computeDistance(final GeoPoint point1, final GeoPoint point2) {
-    return point1.normalDistance(point2);
-  }
-  
-  @Override
-  public double computeDistance(final GeoPoint point1, final double x2, final double y2, final double z2) {
-    return point1.normalDistance(x2,y2,z2);
-  }
-
-  @Override
-  public double computeDistance(final PlanetModel planetModel, final Plane plane, final GeoPoint point, final Membership... bounds) {
-    return plane.normalDistance(point, bounds);
-  }
-  
-  @Override
-  public double computeDistance(final PlanetModel planetModel, final Plane plane, final double x, final double y, final double z, final Membership... bounds) {
-    return plane.normalDistance(x,y,z, bounds);
-  }
-
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/NormalSquaredDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/NormalSquaredDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/NormalSquaredDistance.java
deleted file mode 100644
index 035fd40..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/NormalSquaredDistance.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Normal squared distance computation style.
- *
- * @lucene.experimental
- */
-public class NormalSquaredDistance implements DistanceStyle {
-  
-  /** A convenient instance */
-  public final static NormalSquaredDistance INSTANCE = new NormalSquaredDistance();
-  
-  /** Constructor.
-   */
-  public NormalSquaredDistance() {
-  }
-  
-  @Override
-  public double computeDistance(final GeoPoint point1, final GeoPoint point2) {
-    return point1.normalDistanceSquared(point2);
-  }
-  
-  @Override
-  public double computeDistance(final GeoPoint point1, final double x2, final double y2, final double z2) {
-    return point1.normalDistanceSquared(x2,y2,z2);
-  }
-
-  @Override
-  public double computeDistance(final PlanetModel planetModel, final Plane plane, final GeoPoint point, final Membership... bounds) {
-    return plane.normalDistanceSquared(point, bounds);
-  }
-  
-  @Override
-  public double computeDistance(final PlanetModel planetModel, final Plane plane, final double x, final double y, final double z, final Membership... bounds) {
-    return plane.normalDistanceSquared(x,y,z, bounds);
-  }
-
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Plane.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Plane.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Plane.java
deleted file mode 100755
index 07d0c5b..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Plane.java
+++ /dev/null
@@ -1,1657 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * We know about three kinds of planes.  First kind: general plain through two points and origin
- * Second kind: horizontal plane at specified height.  Third kind: vertical plane with specified x and y value, through origin.
- *
- * @lucene.experimental
- */
-public class Plane extends Vector {
-  /** An array with no points in it */
-  protected final static GeoPoint[] NO_POINTS = new GeoPoint[0];
-  /** An array with no bounds in it */
-  protected final static Membership[] NO_BOUNDS = new Membership[0];
-  /** A vertical plane normal to the Y axis */
-  protected final static Plane normalYPlane = new Plane(0.0,1.0,0.0,0.0);
-  /** A vertical plane normal to the X axis */
-  protected final static Plane normalXPlane = new Plane(1.0,0.0,0.0,0.0);
-  /** A vertical plane normal to the Z axis */
-  protected final static Plane normalZPlane = new Plane(0.0,0.0,1.0,0.0);
-
-  /** Ax + By + Cz + D = 0 */
-  public final double D;
-
-  /**
-   * Construct a plane with all four coefficients defined.
-   *@param A is A
-   *@param B is B
-   *@param C is C
-   *@param D is D
-   */
-  public Plane(final double A, final double B, final double C, final double D) {
-    super(A, B, C);
-    this.D = D;
-  }
-
-  /**
-   * Construct a plane through two points and origin.
-   *
-   * @param A is the first point (origin based).
-   * @param B is the second point (origin based).
-   */
-  public Plane(final Vector A, final Vector B) {
-    super(A, B);
-    D = 0.0;
-  }
-
-  /**
-   * Construct a horizontal plane at a specified Z.
-   *
-   * @param planetModel is the planet model.
-   * @param sinLat is the sin(latitude).
-   */
-  public Plane(final PlanetModel planetModel, final double sinLat) {
-    super(0.0, 0.0, 1.0);
-    D = -sinLat * computeDesiredEllipsoidMagnitude(planetModel, sinLat);
-  }
-
-  /**
-   * Construct a vertical plane through a specified
-   * x, y and origin.
-   *
-   * @param x is the specified x value.
-   * @param y is the specified y value.
-   */
-  public Plane(final double x, final double y) {
-    super(y, -x, 0.0);
-    D = 0.0;
-  }
-
-  /**
-   * Construct a plane with a specific vector, and D offset
-   * from origin.
-   * @param v is the normal vector.
-   * @param D is the D offset from the origin.
-   */
-  public Plane(final Vector v, final double D) {
-    super(v.x, v.y, v.z);
-    this.D = D;
-  }
-
-  /** Construct the most accurate normalized plane through an x-y point and including the Z axis.
-   * If none of the points can determine the plane, return null.
-   * @param planePoints is a set of points to choose from.  The best one for constructing the most precise plane is picked.
-   * @return the plane
-   */
-  public static Plane constructNormalizedZPlane(final Vector... planePoints) {
-    // Pick the best one (with the greatest x-y distance)
-    double bestDistance = 0.0;
-    Vector bestPoint = null;
-    for (final Vector point : planePoints) {
-      final double pointDist = point.x * point.x + point.y * point.y;
-      if (pointDist > bestDistance) {
-        bestDistance = pointDist;
-        bestPoint = point;
-      }
-    }
-    return constructNormalizedZPlane(bestPoint.x, bestPoint.y);
-  }
-
-  /** Construct the most accurate normalized plane through an x-z point and including the Y axis.
-   * If none of the points can determine the plane, return null.
-   * @param planePoints is a set of points to choose from.  The best one for constructing the most precise plane is picked.
-   * @return the plane
-   */
-  public static Plane constructNormalizedYPlane(final Vector... planePoints) {
-    // Pick the best one (with the greatest x-z distance)
-    double bestDistance = 0.0;
-    Vector bestPoint = null;
-    for (final Vector point : planePoints) {
-      final double pointDist = point.x * point.x + point.z * point.z;
-      if (pointDist > bestDistance) {
-        bestDistance = pointDist;
-        bestPoint = point;
-      }
-    }
-    return constructNormalizedYPlane(bestPoint.x, bestPoint.z, 0.0);
-  }
-
-  /** Construct the most accurate normalized plane through an y-z point and including the X axis.
-   * If none of the points can determine the plane, return null.
-   * @param planePoints is a set of points to choose from.  The best one for constructing the most precise plane is picked.
-   * @return the plane
-   */
-  public static Plane constructNormalizedXPlane(final Vector... planePoints) {
-    // Pick the best one (with the greatest y-z distance)
-    double bestDistance = 0.0;
-    Vector bestPoint = null;
-    for (final Vector point : planePoints) {
-      final double pointDist = point.y * point.y + point.z * point.z;
-      if (pointDist > bestDistance) {
-        bestDistance = pointDist;
-        bestPoint = point;
-      }
-    }
-    return constructNormalizedXPlane(bestPoint.y, bestPoint.z, 0.0);
-  }
-
-  /** Construct a normalized plane through an x-y point and including the Z axis.
-   * If the x-y point is at (0,0), return null.
-   * @param x is the x value.
-   * @param y is the y value.
-   * @return a plane passing through the Z axis and (x,y,0).
-   */
-  public static Plane constructNormalizedZPlane(final double x, final double y) {
-    if (Math.abs(x) < MINIMUM_RESOLUTION && Math.abs(y) < MINIMUM_RESOLUTION)
-      return null;
-    final double denom = 1.0 / Math.sqrt(x*x + y*y);
-    return new Plane(y * denom, -x * denom, 0.0, 0.0);
-  }
-
-  /** Construct a normalized plane through an x-z point and parallel to the Y axis.
-   * If the x-z point is at (0,0), return null.
-   * @param x is the x value.
-   * @param z is the z value.
-   * @param DValue is the offset from the origin for the plane.
-   * @return a plane parallel to the Y axis and perpendicular to the x and z values given.
-   */
-  public static Plane constructNormalizedYPlane(final double x, final double z, final double DValue) {
-    if (Math.abs(x) < MINIMUM_RESOLUTION && Math.abs(z) < MINIMUM_RESOLUTION)
-      return null;
-    final double denom = 1.0 / Math.sqrt(x*x + z*z);
-    return new Plane(z * denom, 0.0, -x * denom, DValue);
-  }
-
-  /** Construct a normalized plane through a y-z point and parallel to the X axis.
-   * If the y-z point is at (0,0), return null.
-   * @param y is the y value.
-   * @param z is the z value.
-   * @param DValue is the offset from the origin for the plane.
-   * @return a plane parallel to the X axis and perpendicular to the y and z values given.
-   */
-  public static Plane constructNormalizedXPlane(final double y, final double z, final double DValue) {
-    if (Math.abs(y) < MINIMUM_RESOLUTION && Math.abs(z) < MINIMUM_RESOLUTION)
-      return null;
-    final double denom = 1.0 / Math.sqrt(y*y + z*z);
-    return new Plane(0.0, z * denom, -y * denom, DValue);
-  }
-  
-  /**
-   * Evaluate the plane equation for a given point, as represented
-   * by a vector.
-   *
-   * @param v is the vector.
-   * @return the result of the evaluation.
-   */
-  public double evaluate(final Vector v) {
-    return dotProduct(v) + D;
-  }
-
-  /**
-   * Evaluate the plane equation for a given point, as represented
-   * by a vector.
-   * @param x is the x value.
-   * @param y is the y value.
-   * @param z is the z value.
-   * @return the result of the evaluation.
-   */
-  public double evaluate(final double x, final double y, final double z) {
-    return dotProduct(x, y, z) + D;
-  }
-
-  /**
-   * Evaluate the plane equation for a given point, as represented
-   * by a vector.
-   *
-   * @param v is the vector.
-   * @return true if the result is on the plane.
-   */
-  public boolean evaluateIsZero(final Vector v) {
-    return Math.abs(evaluate(v)) < MINIMUM_RESOLUTION;
-  }
-
-  /**
-   * Evaluate the plane equation for a given point, as represented
-   * by a vector.
-   *
-   * @param x is the x value.
-   * @param y is the y value.
-   * @param z is the z value.
-   * @return true if the result is on the plane.
-   */
-  public boolean evaluateIsZero(final double x, final double y, final double z) {
-    return Math.abs(evaluate(x, y, z)) < MINIMUM_RESOLUTION;
-  }
-
-  /**
-   * Build a normalized plane, so that the vector is normalized.
-   *
-   * @return the normalized plane object, or null if the plane is indeterminate.
-   */
-  public Plane normalize() {
-    Vector normVect = super.normalize();
-    if (normVect == null)
-      return null;
-    return new Plane(normVect, this.D);
-  }
-
-  /** Compute arc distance from plane to a vector expressed with a {@link GeoPoint}.
-   *  @see #arcDistance(PlanetModel, double, double, double, Membership...) */
-  public double arcDistance(final PlanetModel planetModel, final GeoPoint v, final Membership... bounds) {
-    return arcDistance(planetModel, v.x, v.y, v.z, bounds);
-  }
-    
-  /**
-   * Compute arc distance from plane to a vector.
-   * @param planetModel is the planet model.
-   * @param x is the x vector value.
-   * @param y is the y vector value.
-   * @param z is the z vector value.
-   * @param bounds are the bounds which constrain the intersection point.
-   * @return the arc distance.
-   */
-  public double arcDistance(final PlanetModel planetModel, final double x, final double y, final double z, final Membership... bounds) {
-
-    if (evaluateIsZero(x,y,z)) {
-      if (meetsAllBounds(x,y,z, bounds))
-        return 0.0;
-      return Double.MAX_VALUE;
-    }
-    
-    // First, compute the perpendicular plane.
-    final Plane perpPlane = new Plane(this.y * z - this.z * y, this.z * x - this.x * z, this.x * y - this.y * x, 0.0);
-
-    // We need to compute the intersection of two planes on the geo surface: this one, and its perpendicular.
-    // Then, we need to choose which of the two points we want to compute the distance to.  We pick the
-    // shorter distance always.
-    
-    final GeoPoint[] intersectionPoints = findIntersections(planetModel, perpPlane);
-    
-    // For each point, compute a linear distance, and take the minimum of them
-    double minDistance = Double.MAX_VALUE;
-    
-    for (final GeoPoint intersectionPoint : intersectionPoints) {
-      if (meetsAllBounds(intersectionPoint, bounds)) {
-        final double theDistance = intersectionPoint.arcDistance(x,y,z);
-        if (theDistance < minDistance) {
-          minDistance = theDistance;
-        }
-      }
-    }
-    return minDistance;
-
-  }
-
-  /**
-   * Compute normal distance from plane to a vector.
-   * @param v is the vector.
-   * @param bounds are the bounds which constrain the intersection point.
-   * @return the normal distance.
-   */
-  public double normalDistance(final Vector v, final Membership... bounds) {
-    return normalDistance(v.x, v.y, v.z, bounds);
-  }
-    
-  /**
-   * Compute normal distance from plane to a vector.
-   * @param x is the vector x.
-   * @param y is the vector y.
-   * @param z is the vector z.
-   * @param bounds are the bounds which constrain the intersection point.
-   * @return the normal distance.
-   */
-  public double normalDistance(final double x, final double y, final double z, final Membership... bounds) {
-
-    final double dist = evaluate(x,y,z);
-    final double perpX = x - dist * this.x;
-    final double perpY = y - dist * this.y;
-    final double perpZ = z - dist * this.z;
-
-    if (!meetsAllBounds(perpX, perpY, perpZ, bounds)) {
-      return Double.MAX_VALUE;
-    }
-    
-    return Math.abs(dist);
-  }
-  
-  /**
-   * Compute normal distance squared from plane to a vector.
-   * @param v is the vector.
-   * @param bounds are the bounds which constrain the intersection point.
-   * @return the normal distance squared.
-   */
-  public double normalDistanceSquared(final Vector v, final Membership... bounds) {
-    return normalDistanceSquared(v.x, v.y, v.z, bounds);
-  }
-  
-  /**
-   * Compute normal distance squared from plane to a vector.
-   * @param x is the vector x.
-   * @param y is the vector y.
-   * @param z is the vector z.
-   * @param bounds are the bounds which constrain the intersection point.
-   * @return the normal distance squared.
-   */
-  public double normalDistanceSquared(final double x, final double y, final double z, final Membership... bounds) {
-    final double normal = normalDistance(x,y,z,bounds);
-    if (normal == Double.MAX_VALUE)
-      return normal;
-    return normal * normal;
-  }
-
-  /**
-   * Compute linear distance from plane to a vector.  This is defined
-   * as the distance from the given point to the nearest intersection of 
-   * this plane with the planet surface.
-   * @param planetModel is the planet model.
-   * @param v is the point.
-   * @param bounds are the bounds which constrain the intersection point.
-   * @return the linear distance.
-   */
-  public double linearDistance(final PlanetModel planetModel, final GeoPoint v, final Membership... bounds) {
-    return linearDistance(planetModel, v.x, v.y, v.z, bounds);
-  }
-    
-  /**
-   * Compute linear distance from plane to a vector.  This is defined
-   * as the distance from the given point to the nearest intersection of 
-   * this plane with the planet surface.
-   * @param planetModel is the planet model.
-   * @param x is the vector x.
-   * @param y is the vector y.
-   * @param z is the vector z.
-   * @param bounds are the bounds which constrain the intersection point.
-   * @return the linear distance.
-   */
-  public double linearDistance(final PlanetModel planetModel, final double x, final double y, final double z, final Membership... bounds) {
-    if (evaluateIsZero(x,y,z)) {
-      if (meetsAllBounds(x,y,z, bounds))
-        return 0.0;
-      return Double.MAX_VALUE;
-    }
-    
-    // First, compute the perpendicular plane.
-    final Plane perpPlane = new Plane(this.y * z - this.z * y, this.z * x - this.x * z, this.x * y - this.y * x, 0.0);
-
-    // We need to compute the intersection of two planes on the geo surface: this one, and its perpendicular.
-    // Then, we need to choose which of the two points we want to compute the distance to.  We pick the
-    // shorter distance always.
-    
-    final GeoPoint[] intersectionPoints = findIntersections(planetModel, perpPlane);
-    
-    // For each point, compute a linear distance, and take the minimum of them
-    double minDistance = Double.MAX_VALUE;
-    
-    for (final GeoPoint intersectionPoint : intersectionPoints) {
-      if (meetsAllBounds(intersectionPoint, bounds)) {
-        final double theDistance = intersectionPoint.linearDistance(x,y,z);
-        if (theDistance < minDistance) {
-          minDistance = theDistance;
-        }
-      }
-    }
-    return minDistance;
-  }
-      
-  /**
-   * Compute linear distance squared from plane to a vector.  This is defined
-   * as the distance from the given point to the nearest intersection of 
-   * this plane with the planet surface.
-   * @param planetModel is the planet model.
-   * @param v is the point.
-   * @param bounds are the bounds which constrain the intersection point.
-   * @return the linear distance squared.
-   */
-  public double linearDistanceSquared(final PlanetModel planetModel, final GeoPoint v, final Membership... bounds) {
-    return linearDistanceSquared(planetModel, v.x, v.y, v.z, bounds);
-  }
-  
-  /**
-   * Compute linear distance squared from plane to a vector.  This is defined
-   * as the distance from the given point to the nearest intersection of 
-   * this plane with the planet surface.
-   * @param planetModel is the planet model.
-   * @param x is the vector x.
-   * @param y is the vector y.
-   * @param z is the vector z.
-   * @param bounds are the bounds which constrain the intersection point.
-   * @return the linear distance squared.
-   */
-  public double linearDistanceSquared(final PlanetModel planetModel, final double x, final double y, final double z, final Membership... bounds) {
-    final double linearDistance = linearDistance(planetModel, x, y, z, bounds);
-    return linearDistance * linearDistance;
-  }
-
-  /**
-   * Find points on the boundary of the intersection of a plane and the unit sphere,
-   * given a starting point, and ending point, and a list of proportions of the arc (e.g. 0.25, 0.5, 0.75).
-   * The angle between the starting point and ending point is assumed to be less than pi.
-   * @param start is the start point.
-   * @param end is the end point.
-   * @param proportions is an array of fractional proportions measured between start and end.
-   * @return an array of points corresponding to the proportions passed in.
-   */
-  public GeoPoint[] interpolate(final GeoPoint start, final GeoPoint end, final double[] proportions) {
-    // Steps:
-    // (1) Translate (x0,y0,z0) of endpoints into origin-centered place:
-    // x1 = x0 + D*A
-    // y1 = y0 + D*B
-    // z1 = z0 + D*C
-    // (2) Rotate counterclockwise in x-y:
-    // ra = -atan2(B,A)
-    // x2 = x1 cos ra - y1 sin ra
-    // y2 = x1 sin ra + y1 cos ra
-    // z2 = z1
-    // Faster:
-    // cos ra = A/sqrt(A^2+B^2+C^2)
-    // sin ra = -B/sqrt(A^2+B^2+C^2)
-    // cos (-ra) = A/sqrt(A^2+B^2+C^2)
-    // sin (-ra) = B/sqrt(A^2+B^2+C^2)
-    // (3) Rotate clockwise in x-z:
-    // ha = pi/2 - asin(C/sqrt(A^2+B^2+C^2))
-    // x3 = x2 cos ha - z2 sin ha
-    // y3 = y2
-    // z3 = x2 sin ha + z2 cos ha
-    // At this point, z3 should be zero.
-    // Faster:
-    // sin(ha) = cos(asin(C/sqrt(A^2+B^2+C^2))) = sqrt(1 - C^2/(A^2+B^2+C^2)) = sqrt(A^2+B^2)/sqrt(A^2+B^2+C^2)
-    // cos(ha) = sin(asin(C/sqrt(A^2+B^2+C^2))) = C/sqrt(A^2+B^2+C^2)
-    // (4) Compute interpolations by getting longitudes of original points
-    // la = atan2(y3,x3)
-    // (5) Rotate new points (xN0, yN0, zN0) counter-clockwise in x-z:
-    // ha = -(pi - asin(C/sqrt(A^2+B^2+C^2)))
-    // xN1 = xN0 cos ha - zN0 sin ha
-    // yN1 = yN0
-    // zN1 = xN0 sin ha + zN0 cos ha
-    // (6) Rotate new points clockwise in x-y:
-    // ra = atan2(B,A)
-    // xN2 = xN1 cos ra - yN1 sin ra
-    // yN2 = xN1 sin ra + yN1 cos ra
-    // zN2 = zN1
-    // (7) Translate new points:
-    // xN3 = xN2 - D*A
-    // yN3 = yN2 - D*B
-    // zN3 = zN2 - D*C
-
-    // First, calculate the angles and their sin/cos values
-    double A = x;
-    double B = y;
-    double C = z;
-
-    // Translation amounts
-    final double transX = -D * A;
-    final double transY = -D * B;
-    final double transZ = -D * C;
-
-    double cosRA;
-    double sinRA;
-    double cosHA;
-    double sinHA;
-
-    double magnitude = magnitude();
-    if (magnitude >= MINIMUM_RESOLUTION) {
-      final double denom = 1.0 / magnitude;
-      A *= denom;
-      B *= denom;
-      C *= denom;
-
-      // cos ra = A/sqrt(A^2+B^2+C^2)
-      // sin ra = -B/sqrt(A^2+B^2+C^2)
-      // cos (-ra) = A/sqrt(A^2+B^2+C^2)
-      // sin (-ra) = B/sqrt(A^2+B^2+C^2)
-      final double xyMagnitude = Math.sqrt(A * A + B * B);
-      if (xyMagnitude >= MINIMUM_RESOLUTION) {
-        final double xyDenom = 1.0 / xyMagnitude;
-        cosRA = A * xyDenom;
-        sinRA = -B * xyDenom;
-      } else {
-        cosRA = 1.0;
-        sinRA = 0.0;
-      }
-
-      // sin(ha) = cos(asin(C/sqrt(A^2+B^2+C^2))) = sqrt(1 - C^2/(A^2+B^2+C^2)) = sqrt(A^2+B^2)/sqrt(A^2+B^2+C^2)
-      // cos(ha) = sin(asin(C/sqrt(A^2+B^2+C^2))) = C/sqrt(A^2+B^2+C^2)
-      sinHA = xyMagnitude;
-      cosHA = C;
-    } else {
-      cosRA = 1.0;
-      sinRA = 0.0;
-      cosHA = 1.0;
-      sinHA = 0.0;
-    }
-
-    // Forward-translate the start and end points
-    final Vector modifiedStart = modify(start, transX, transY, transZ, sinRA, cosRA, sinHA, cosHA);
-    final Vector modifiedEnd = modify(end, transX, transY, transZ, sinRA, cosRA, sinHA, cosHA);
-    if (Math.abs(modifiedStart.z) >= MINIMUM_RESOLUTION)
-      throw new IllegalArgumentException("Start point was not on plane: " + modifiedStart.z);
-    if (Math.abs(modifiedEnd.z) >= MINIMUM_RESOLUTION)
-      throw new IllegalArgumentException("End point was not on plane: " + modifiedEnd.z);
-
-    // Compute the angular distance between start and end point
-    final double startAngle = Math.atan2(modifiedStart.y, modifiedStart.x);
-    final double endAngle = Math.atan2(modifiedEnd.y, modifiedEnd.x);
-
-    final double startMagnitude = Math.sqrt(modifiedStart.x * modifiedStart.x + modifiedStart.y * modifiedStart.y);
-    double delta;
-
-    double newEndAngle = endAngle;
-    while (newEndAngle < startAngle) {
-      newEndAngle += Math.PI * 2.0;
-    }
-
-    if (newEndAngle - startAngle <= Math.PI) {
-      delta = newEndAngle - startAngle;
-    } else {
-      double newStartAngle = startAngle;
-      while (newStartAngle < endAngle) {
-        newStartAngle += Math.PI * 2.0;
-      }
-      delta = newStartAngle - endAngle;
-    }
-
-    final GeoPoint[] returnValues = new GeoPoint[proportions.length];
-    for (int i = 0; i < returnValues.length; i++) {
-      final double newAngle = startAngle + proportions[i] * delta;
-      final double sinNewAngle = Math.sin(newAngle);
-      final double cosNewAngle = Math.cos(newAngle);
-      final Vector newVector = new Vector(cosNewAngle * startMagnitude, sinNewAngle * startMagnitude, 0.0);
-      returnValues[i] = reverseModify(newVector, transX, transY, transZ, sinRA, cosRA, sinHA, cosHA);
-    }
-
-    return returnValues;
-  }
-
-  /**
-   * Modify a point to produce a vector in translated/rotated space.
-   * @param start is the start point.
-   * @param transX is the translation x value.
-   * @param transY is the translation y value.
-   * @param transZ is the translation z value.
-   * @param sinRA is the sine of the ascension angle.
-   * @param cosRA is the cosine of the ascension angle.
-   * @param sinHA is the sine of the height angle.
-   * @param cosHA is the cosine of the height angle.
-   * @return the modified point.
-   */
-  protected static Vector modify(final GeoPoint start, final double transX, final double transY, final double transZ,
-                                 final double sinRA, final double cosRA, final double sinHA, final double cosHA) {
-    return start.translate(transX, transY, transZ).rotateXY(sinRA, cosRA).rotateXZ(sinHA, cosHA);
-  }
-
-  /**
-   * Reverse modify a point to produce a GeoPoint in normal space.
-   * @param point is the translated point.
-   * @param transX is the translation x value.
-   * @param transY is the translation y value.
-   * @param transZ is the translation z value.
-   * @param sinRA is the sine of the ascension angle.
-   * @param cosRA is the cosine of the ascension angle.
-   * @param sinHA is the sine of the height angle.
-   * @param cosHA is the cosine of the height angle.
-   * @return the original point.
-   */
-  protected static GeoPoint reverseModify(final Vector point, final double transX, final double transY, final double transZ,
-                                          final double sinRA, final double cosRA, final double sinHA, final double cosHA) {
-    final Vector result = point.rotateXZ(-sinHA, cosHA).rotateXY(-sinRA, cosRA).translate(-transX, -transY, -transZ);
-    return new GeoPoint(result.x, result.y, result.z);
-  }
-
-  /**
-   * Public version of findIntersections.
-   * @param planetModel is the planet model.
-   * @param q is the plane to intersect with.
-   * @param bounds are the bounds to consider to determine legal intersection points.
-   * @return the set of legal intersection points.
-   */
-  public GeoPoint[] findIntersections(final PlanetModel planetModel, final Plane q, final Membership... bounds) {
-    if (isNumericallyIdentical(q)) {
-      return null;
-    }
-    return findIntersections(planetModel, q, bounds, NO_BOUNDS);
-  }
-  
-  /**
-   * Find the intersection points between two planes, given a set of bounds.
-   *
-   * @param planetModel is the planet model to use in finding points.
-   * @param q          is the plane to intersect with.
-   * @param bounds     is the set of bounds.
-   * @param moreBounds is another set of bounds.
-   * @return the intersection point(s) on the unit sphere, if there are any.
-   */
-  protected GeoPoint[] findIntersections(final PlanetModel planetModel, final Plane q, final Membership[] bounds, final Membership[] moreBounds) {
-    //System.err.println("Looking for intersection between plane "+this+" and plane "+q+" within bounds");
-    // Unnormalized, unchecked...
-    final Vector lineVector = new Vector(y * q.z - z * q.y, z * q.x - x * q.z, x * q.y - y * q.x);
-    if (Math.abs(lineVector.x) < MINIMUM_RESOLUTION && Math.abs(lineVector.y) < MINIMUM_RESOLUTION && Math.abs(lineVector.z) < MINIMUM_RESOLUTION) {
-      // Degenerate case: parallel planes
-      //System.err.println(" planes are parallel - no intersection");
-      return NO_POINTS;
-    }
-
-    // The line will have the equation: A t + A0 = x, B t + B0 = y, C t + C0 = z.
-    // We have A, B, and C.  In order to come up with A0, B0, and C0, we need to find a point that is on both planes.
-    // To do this, we find the largest vector value (either x, y, or z), and look for a point that solves both plane equations
-    // simultaneous.  For example, let's say that the vector is (0.5,0.5,1), and the two plane equations are:
-    // 0.7 x + 0.3 y + 0.1 z + 0.0 = 0
-    // and
-    // 0.9 x - 0.1 y + 0.2 z + 4.0 = 0
-    // Then we'd pick z = 0, so the equations to solve for x and y would be:
-    // 0.7 x + 0.3y = 0.0
-    // 0.9 x - 0.1y = -4.0
-    // ... which can readily be solved using standard linear algebra.  Generally:
-    // Q0 x + R0 y = S0
-    // Q1 x + R1 y = S1
-    // ... can be solved by Cramer's rule:
-    // x = det(S0 R0 / S1 R1) / det(Q0 R0 / Q1 R1)
-    // y = det(Q0 S0 / Q1 S1) / det(Q0 R0 / Q1 R1)
-    // ... where det( a b / c d ) = ad - bc, so:
-    // x = (S0 * R1 - R0 * S1) / (Q0 * R1 - R0 * Q1)
-    // y = (Q0 * S1 - S0 * Q1) / (Q0 * R1 - R0 * Q1)
-    double x0;
-    double y0;
-    double z0;
-    // We try to maximize the determinant in the denominator
-    final double denomYZ = this.y * q.z - this.z * q.y;
-    final double denomXZ = this.x * q.z - this.z * q.x;
-    final double denomXY = this.x * q.y - this.y * q.x;
-    if (Math.abs(denomYZ) >= Math.abs(denomXZ) && Math.abs(denomYZ) >= Math.abs(denomXY)) {
-      // X is the biggest, so our point will have x0 = 0.0
-      if (Math.abs(denomYZ) < MINIMUM_RESOLUTION_SQUARED) {
-        //System.err.println(" Denominator is zero: no intersection");
-        return NO_POINTS;
-      }
-      final double denom = 1.0 / denomYZ;
-      x0 = 0.0;
-      y0 = (-this.D * q.z - this.z * -q.D) * denom;
-      z0 = (this.y * -q.D + this.D * q.y) * denom;
-    } else if (Math.abs(denomXZ) >= Math.abs(denomXY) && Math.abs(denomXZ) >= Math.abs(denomYZ)) {
-      // Y is the biggest, so y0 = 0.0
-      if (Math.abs(denomXZ) < MINIMUM_RESOLUTION_SQUARED) {
-        //System.err.println(" Denominator is zero: no intersection");
-        return NO_POINTS;
-      }
-      final double denom = 1.0 / denomXZ;
-      x0 = (-this.D * q.z - this.z * -q.D) * denom;
-      y0 = 0.0;
-      z0 = (this.x * -q.D + this.D * q.x) * denom;
-    } else {
-      // Z is the biggest, so Z0 = 0.0
-      if (Math.abs(denomXY) < MINIMUM_RESOLUTION_SQUARED) {
-        //System.err.println(" Denominator is zero: no intersection");
-        return NO_POINTS;
-      }
-      final double denom = 1.0 / denomXY;
-      x0 = (-this.D * q.y - this.y * -q.D) * denom;
-      y0 = (this.x * -q.D + this.D * q.x) * denom;
-      z0 = 0.0;
-    }
-
-    // Once an intersecting line is determined, the next step is to intersect that line with the ellipsoid, which
-    // will yield zero, one, or two points.
-    // The ellipsoid equation: 1,0 = x^2/a^2 + y^2/b^2 + z^2/c^2
-    // 1.0 = (At+A0)^2/a^2 + (Bt+B0)^2/b^2 + (Ct+C0)^2/c^2
-    // A^2 t^2 / a^2 + 2AA0t / a^2 + A0^2 / a^2 + B^2 t^2 / b^2 + 2BB0t / b^2 + B0^2 / b^2 + C^2 t^2 / c^2 + 2CC0t / c^2 + C0^2 / c^2  - 1,0 = 0.0
-    // [A^2 / a^2 + B^2 / b^2 + C^2 / c^2] t^2 + [2AA0 / a^2 + 2BB0 / b^2 + 2CC0 / c^2] t + [A0^2 / a^2 + B0^2 / b^2 + C0^2 / c^2 - 1,0] = 0.0
-    // Use the quadratic formula to determine t values and candidate point(s)
-    final double A = lineVector.x * lineVector.x * planetModel.inverseAbSquared +
-      lineVector.y * lineVector.y * planetModel.inverseAbSquared +
-      lineVector.z * lineVector.z * planetModel.inverseCSquared;
-    final double B = 2.0 * (lineVector.x * x0 * planetModel.inverseAbSquared + lineVector.y * y0 * planetModel.inverseAbSquared + lineVector.z * z0 * planetModel.inverseCSquared);
-    final double C = x0 * x0 * planetModel.inverseAbSquared + y0 * y0 * planetModel.inverseAbSquared + z0 * z0 * planetModel.inverseCSquared - 1.0;
-
-    final double BsquaredMinus = B * B - 4.0 * A * C;
-    if (Math.abs(BsquaredMinus) < MINIMUM_RESOLUTION_SQUARED) {
-      //System.err.println(" One point of intersection");
-      final double inverse2A = 1.0 / (2.0 * A);
-      // One solution only
-      final double t = -B * inverse2A;
-      GeoPoint point = new GeoPoint(lineVector.x * t + x0, lineVector.y * t + y0, lineVector.z * t + z0);
-      //System.err.println("  point: "+point);
-      //verifyPoint(planetModel, point, q);
-      if (point.isWithin(bounds, moreBounds))
-        return new GeoPoint[]{point};
-      return NO_POINTS;
-    } else if (BsquaredMinus > 0.0) {
-      //System.err.println(" Two points of intersection");
-      final double inverse2A = 1.0 / (2.0 * A);
-      // Two solutions
-      final double sqrtTerm = Math.sqrt(BsquaredMinus);
-      final double t1 = (-B + sqrtTerm) * inverse2A;
-      final double t2 = (-B - sqrtTerm) * inverse2A;
-      GeoPoint point1 = new GeoPoint(lineVector.x * t1 + x0, lineVector.y * t1 + y0, lineVector.z * t1 + z0);
-      GeoPoint point2 = new GeoPoint(lineVector.x * t2 + x0, lineVector.y * t2 + y0, lineVector.z * t2 + z0);
-      //verifyPoint(planetModel, point1, q);
-      //verifyPoint(planetModel, point2, q);
-      //System.err.println("  "+point1+" and "+point2);
-      if (point1.isWithin(bounds, moreBounds)) {
-        if (point2.isWithin(bounds, moreBounds))
-          return new GeoPoint[]{point1, point2};
-        return new GeoPoint[]{point1};
-      }
-      if (point2.isWithin(bounds, moreBounds))
-        return new GeoPoint[]{point2};
-      return NO_POINTS;
-    } else {
-      //System.err.println(" no solutions - no intersection");
-      return NO_POINTS;
-    }
-  }
-
-  /*
-  protected void verifyPoint(final PlanetModel planetModel, final GeoPoint point, final Plane q) {
-    if (!evaluateIsZero(point))
-      throw new RuntimeException("Intersection point not on original plane; point="+point+", plane="+this);
-    if (!q.evaluateIsZero(point))
-      throw new RuntimeException("Intersection point not on intersected plane; point="+point+", plane="+q);
-    if (Math.abs(point.x * point.x * planetModel.inverseASquared + point.y * point.y * planetModel.inverseBSquared + point.z * point.z * planetModel.inverseCSquared - 1.0) >= MINIMUM_RESOLUTION) 
-      throw new RuntimeException("Intersection point not on ellipsoid; point="+point);
-  }
-  */
-
-  /**
-   * Accumulate (x,y,z) bounds information for this plane, intersected with the unit sphere.
-   * Updates min/max information, using max/min points found
-   * within the specified bounds.
-   *
-   * @param planetModel is the planet model to use in determining bounds.
-   * @param boundsInfo is the xyz info to update with additional bounding information.
-   * @param bounds     are the surfaces delineating what's inside the shape.
-   */
-  public void recordBounds(final PlanetModel planetModel, final XYZBounds boundsInfo, final Membership... bounds) {
-    // Basic plan is to do three intersections of the plane and the planet.
-    // For min/max x, we intersect a vertical plane such that y = 0.
-    // For min/max y, we intersect a vertical plane such that x = 0.
-    // For min/max z, we intersect a vertical plane that is chosen to go through the high point of the arc.
-    // For clarity, load local variables with good names
-    final double A = this.x;
-    final double B = this.y;
-    final double C = this.z;
-
-    // Do Z.  This can be done simply because it is symmetrical.
-    if (!boundsInfo.isSmallestMinZ(planetModel) || !boundsInfo.isLargestMaxZ(planetModel)) {
-      //System.err.println("    computing Z bound");
-      // Compute Z bounds for this arc
-      // With ellipsoids, we really have only one viable way to do this computation.
-      // Specifically, we compute an appropriate vertical plane, based on the current plane's x-y orientation, and
-      // then intersect it with this one and with the ellipsoid.  This gives us zero, one, or two points to use
-      // as bounds.
-      // There is one special case: horizontal circles.  These require TWO vertical planes: one for the x, and one for
-      // the y, and we use all four resulting points in the bounds computation.
-      if ((Math.abs(A) >= MINIMUM_RESOLUTION || Math.abs(B) >= MINIMUM_RESOLUTION)) {
-        // NOT a degenerate case
-        //System.err.println("    not degenerate");
-        final Plane normalizedZPlane = constructNormalizedZPlane(A,B);
-        final GeoPoint[] points = findIntersections(planetModel, normalizedZPlane, bounds, NO_BOUNDS);
-        for (final GeoPoint point : points) {
-          assert planetModel.pointOnSurface(point);
-          //System.err.println("      Point = "+point+"; this.evaluate(point)="+this.evaluate(point)+"; normalizedZPlane.evaluate(point)="+normalizedZPlane.evaluate(point));
-          addPoint(boundsInfo, bounds, point);
-        }
-      } else {
-        // Since a==b==0, any plane including the Z axis suffices.
-        //System.err.println("      Perpendicular to z");
-        final GeoPoint[] points = findIntersections(planetModel, normalYPlane, NO_BOUNDS, NO_BOUNDS);
-        boundsInfo.addZValue(points[0]);
-      }
-    }
-
-    // First, compute common subexpressions
-    final double k = 1.0 / ((x*x + y*y)*planetModel.ab*planetModel.ab + z*z*planetModel.c*planetModel.c);
-    final double abSquared = planetModel.ab * planetModel.ab;
-    final double cSquared = planetModel.c * planetModel.c;
-    final double ASquared = A * A;
-    final double BSquared = B * B;
-    final double CSquared = C * C;
-    
-    final double r = 2.0*D*k;
-    final double rSquared = r * r;
-    
-    if (!boundsInfo.isSmallestMinX(planetModel) || !boundsInfo.isLargestMaxX(planetModel)) {
-      // For min/max x, we need to use lagrange multipliers.
-      //
-      // For this, we need grad(F(x,y,z)) = (dF/dx, dF/dy, dF/dz).
-      //
-      // Minimize and maximize f(x,y,z) = x, with respect to g(x,y,z) = Ax + By + Cz - D and h(x,y,z) = x^2/ab^2 + y^2/ab^2 + z^2/c^2 - 1
-      //
-      // grad(f(x,y,z)) = (1,0,0)
-      // grad(g(x,y,z)) = (A,B,C)
-      // grad(h(x,y,z)) = (2x/ab^2,2y/ab^2,2z/c^2)
-      //
-      // Equations we need to simultaneously solve:
-      // 
-      // grad(f(x,y,z)) = l * grad(g(x,y,z)) + m * grad(h(x,y,z))
-      // g(x,y,z) = 0
-      // h(x,y,z) = 0
-      // 
-      // Equations:
-      // 1 = l*A + m*2x/ab^2
-      // 0 = l*B + m*2y/ab^2
-      // 0 = l*C + m*2z/c^2
-      // Ax + By + Cz + D = 0
-      // x^2/ab^2 + y^2/ab^2 + z^2/c^2 - 1 = 0
-      // 
-      // Solve for x,y,z in terms of (l, m):
-      // 
-      // x = ((1 - l*A) * ab^2 ) / (2 * m)
-      // y = (-l*B * ab^2) / ( 2 * m)
-      // z = (-l*C * c^2)/ (2 * m)
-      // 
-      // Two equations, two unknowns:
-      // 
-      // A * (((1 - l*A) * ab^2 ) / (2 * m)) + B * ((-l*B * ab^2) / ( 2 * m)) + C * ((-l*C * c^2)/ (2 * m)) + D = 0
-      // 
-      // and
-      // 
-      // (((1 - l*A) * ab^2 ) / (2 * m))^2/ab^2 + ((-l*B * ab^2) / ( 2 * m))^2/ab^2 + ((-l*C * c^2)/ (2 * m))^2/c^2 - 1 = 0
-      // 
-      // Simple: solve for l and m, then find x from it.
-      // 
-      // (a) Use first equation to find l in terms of m.
-      // 
-      // A * (((1 - l*A) * ab^2 ) / (2 * m)) + B * ((-l*B * ab^2) / ( 2 * m)) + C * ((-l*C * c^2)/ (2 * m)) + D = 0
-      // A * ((1 - l*A) * ab^2 ) + B * (-l*B * ab^2) + C * (-l*C * c^2) + D * 2 * m = 0
-      // A * ab^2 - l*A^2* ab^2 - B^2 * l * ab^2 - C^2 * l * c^2 + D * 2 * m = 0
-      // - l *(A^2* ab^2 + B^2 * ab^2 + C^2 * c^2) + (A * ab^2 + D * 2 * m) = 0
-      // l = (A * ab^2 + D * 2 * m) / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2)
-      // l = A * ab^2 / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2) + m * 2 * D / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2)
-      // 
-      // For convenience:
-      // 
-      // k = 1.0 / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2)
-      // 
-      // Then:
-      // 
-      // l = A * ab^2 * k + m * 2 * D * k
-      // l = k * (A*ab^2 + m*2*D)
-      //
-      // For further convenience:
-      //
-      // q = A*ab^2*k
-      // r = 2*D*k
-      //
-      // l = (r*m + q)
-      // l^2 = (r^2 * m^2 + 2*r*m*q + q^2)
-      // 
-      // (b) Simplify the second equation before substitution
-      // 
-      // (((1 - l*A) * ab^2 ) / (2 * m))^2/ab^2 + ((-l*B * ab^2) / ( 2 * m))^2/ab^2 + ((-l*C * c^2)/ (2 * m))^2/c^2 - 1 = 0
-      // ((1 - l*A) * ab^2 )^2/ab^2 + (-l*B * ab^2)^2/ab^2 + (-l*C * c^2)^2/c^2 = 4 * m^2
-      // (1 - l*A)^2 * ab^2 + (-l*B)^2 * ab^2 + (-l*C)^2 * c^2 = 4 * m^2
-      // (1 - 2*l*A + l^2*A^2) * ab^2 + l^2*B^2 * ab^2 + l^2*C^2 * c^2 = 4 * m^2
-      // ab^2 - 2*A*ab^2*l + A^2*ab^2*l^2 + B^2*ab^2*l^2 + C^2*c^2*l^2 - 4*m^2 = 0
-      // 
-      // (c) Substitute for l, l^2
-      //
-      // ab^2 - 2*A*ab^2*(r*m + q) + A^2*ab^2*(r^2 * m^2 + 2*r*m*q + q^2) + B^2*ab^2*(r^2 * m^2 + 2*r*m*q + q^2) + C^2*c^2*(r^2 * m^2 + 2*r*m*q + q^2) - 4*m^2 = 0
-      // ab^2 - 2*A*ab^2*r*m - 2*A*ab^2*q + A^2*ab^2*r^2*m^2 + 2*A^2*ab^2*r*q*m +
-      //        A^2*ab^2*q^2 + B^2*ab^2*r^2*m^2 + 2*B^2*ab^2*r*q*m + B^2*ab^2*q^2 + C^2*c^2*r^2*m^2 + 2*C^2*c^2*r*q*m + C^2*c^2*q^2 - 4*m^2 = 0
-      //
-      // (d) Group
-      //
-      // m^2 * [A^2*ab^2*r^2 + B^2*ab^2*r^2 + C^2*c^2*r^2 - 4] +
-      // m * [- 2*A*ab^2*r + 2*A^2*ab^2*r*q + 2*B^2*ab^2*r*q + 2*C^2*c^2*r*q] +
-      // [ab^2 - 2*A*ab^2*q + A^2*ab^2*q^2 + B^2*ab^2*q^2 + C^2*c^2*q^2]  =  0
-      
-      //System.err.println("    computing X bound");
-      
-      // Useful subexpressions for this bound
-      final double q = A*abSquared*k;
-      final double qSquared = q * q;
-
-      // Quadratic equation
-      final double a = ASquared*abSquared*rSquared + BSquared*abSquared*rSquared + CSquared*cSquared*rSquared - 4.0;
-      final double b = - 2.0*A*abSquared*r + 2.0*ASquared*abSquared*r*q + 2.0*BSquared*abSquared*r*q + 2.0*CSquared*cSquared*r*q;
-      final double c = abSquared - 2.0*A*abSquared*q + ASquared*abSquared*qSquared + BSquared*abSquared*qSquared + CSquared*cSquared*qSquared;
-      
-      if (Math.abs(a) >= MINIMUM_RESOLUTION_SQUARED) {
-        final double sqrtTerm = b*b - 4.0*a*c;
-        if (Math.abs(sqrtTerm) < MINIMUM_RESOLUTION_SQUARED) {
-          // One solution
-          final double m = -b / (2.0 * a);
-          final double l = r * m + q;
-          // x = ((1 - l*A) * ab^2 ) / (2 * m)
-          // y = (-l*B * ab^2) / ( 2 * m)
-          // z = (-l*C * c^2)/ (2 * m)
-          final double denom0 = 0.5 / m;
-          final GeoPoint thePoint = new GeoPoint((1.0-l*A) * abSquared * denom0, -l*B * abSquared * denom0, -l*C * cSquared * denom0);
-          //Math is not quite accurate enough for this
-          //assert planetModel.pointOnSurface(thePoint): "Point: "+thePoint+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
-          //  (thePoint.x*thePoint.x*planetModel.inverseAb*planetModel.inverseAb + thePoint.y*thePoint.y*planetModel.inverseAb*planetModel.inverseAb + thePoint.z*thePoint.z*planetModel.inverseC*planetModel.inverseC);
-          //assert evaluateIsZero(thePoint): "Evaluation of point: "+evaluate(thePoint);
-          addPoint(boundsInfo, bounds, thePoint);
-        } else if (sqrtTerm > 0.0) {
-          // Two solutions
-          final double sqrtResult = Math.sqrt(sqrtTerm);
-          final double commonDenom = 0.5/a;
-          final double m1 = (-b + sqrtResult) * commonDenom;
-          assert Math.abs(a * m1 * m1 + b * m1 + c) < MINIMUM_RESOLUTION;
-          final double m2 = (-b - sqrtResult) * commonDenom;
-          assert Math.abs(a * m2 * m2 + b * m2 + c) < MINIMUM_RESOLUTION;
-          final double l1 = r * m1 + q;
-          final double l2 = r * m2 + q;
-          // x = ((1 - l*A) * ab^2 ) / (2 * m)
-          // y = (-l*B * ab^2) / ( 2 * m)
-          // z = (-l*C * c^2)/ (2 * m)
-          final double denom1 = 0.5 / m1;
-          final double denom2 = 0.5 / m2;
-          final GeoPoint thePoint1 = new GeoPoint((1.0-l1*A) * abSquared * denom1, -l1*B * abSquared * denom1, -l1*C * cSquared * denom1);
-          final GeoPoint thePoint2 = new GeoPoint((1.0-l2*A) * abSquared * denom2, -l2*B * abSquared * denom2, -l2*C * cSquared * denom2);
-          //Math is not quite accurate enough for this
-          //assert planetModel.pointOnSurface(thePoint1): "Point1: "+thePoint1+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
-          //  (thePoint1.x*thePoint1.x*planetModel.inverseAb*planetModel.inverseAb + thePoint1.y*thePoint1.y*planetModel.inverseAb*planetModel.inverseAb + thePoint1.z*thePoint1.z*planetModel.inverseC*planetModel.inverseC);
-          //assert planetModel.pointOnSurface(thePoint2): "Point1: "+thePoint2+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
-          //  (thePoint2.x*thePoint2.x*planetModel.inverseAb*planetModel.inverseAb + thePoint2.y*thePoint2.y*planetModel.inverseAb*planetModel.inverseAb + thePoint2.z*thePoint2.z*planetModel.inverseC*planetModel.inverseC);
-          //assert evaluateIsZero(thePoint1): "Evaluation of point1: "+evaluate(thePoint1);
-          //assert evaluateIsZero(thePoint2): "Evaluation of point2: "+evaluate(thePoint2);
-          addPoint(boundsInfo, bounds, thePoint1);
-          addPoint(boundsInfo, bounds, thePoint2);
-        } else {
-          // No solutions
-        }
-      } else if (Math.abs(b) > MINIMUM_RESOLUTION_SQUARED) {
-        //System.err.println("Not x quadratic");
-        // a = 0, so m = - c / b
-        final double m = -c / b;
-        final double l = r * m + q;
-        // x = ((1 - l*A) * ab^2 ) / (2 * m)
-        // y = (-l*B * ab^2) / ( 2 * m)
-        // z = (-l*C * c^2)/ (2 * m)
-        final double denom0 = 0.5 / m;
-        final GeoPoint thePoint = new GeoPoint((1.0-l*A) * abSquared * denom0, -l*B * abSquared * denom0, -l*C * cSquared * denom0);
-        //Math is not quite accurate enough for this
-        //assert planetModel.pointOnSurface(thePoint): "Point: "+thePoint+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
-        //  (thePoint.x*thePoint.x*planetModel.inverseAb*planetModel.inverseAb + thePoint.y*thePoint.y*planetModel.inverseAb*planetModel.inverseAb + thePoint.z*thePoint.z*planetModel.inverseC*planetModel.inverseC);
-        //assert evaluateIsZero(thePoint): "Evaluation of point: "+evaluate(thePoint);
-        addPoint(boundsInfo, bounds, thePoint);
-      } else {
-        // Something went very wrong; a = b = 0
-      }
-    }
-    
-    // Do Y
-    if (!boundsInfo.isSmallestMinY(planetModel) || !boundsInfo.isLargestMaxY(planetModel)) {
-      // For min/max x, we need to use lagrange multipliers.
-      //
-      // For this, we need grad(F(x,y,z)) = (dF/dx, dF/dy, dF/dz).
-      //
-      // Minimize and maximize f(x,y,z) = y, with respect to g(x,y,z) = Ax + By + Cz - D and h(x,y,z) = x^2/ab^2 + y^2/ab^2 + z^2/c^2 - 1
-      //
-      // grad(f(x,y,z)) = (0,1,0)
-      // grad(g(x,y,z)) = (A,B,C)
-      // grad(h(x,y,z)) = (2x/ab^2,2y/ab^2,2z/c^2)
-      //
-      // Equations we need to simultaneously solve:
-      // 
-      // grad(f(x,y,z)) = l * grad(g(x,y,z)) + m * grad(h(x,y,z))
-      // g(x,y,z) = 0
-      // h(x,y,z) = 0
-      // 
-      // Equations:
-      // 0 = l*A + m*2x/ab^2
-      // 1 = l*B + m*2y/ab^2
-      // 0 = l*C + m*2z/c^2
-      // Ax + By + Cz + D = 0
-      // x^2/ab^2 + y^2/ab^2 + z^2/c^2 - 1 = 0
-      // 
-      // Solve for x,y,z in terms of (l, m):
-      // 
-      // x = (-l*A * ab^2 ) / (2 * m)
-      // y = ((1 - l*B) * ab^2) / ( 2 * m)
-      // z = (-l*C * c^2)/ (2 * m)
-      // 
-      // Two equations, two unknowns:
-      // 
-      // A * ((-l*A * ab^2 ) / (2 * m)) + B * (((1 - l*B) * ab^2) / ( 2 * m)) + C * ((-l*C * c^2)/ (2 * m)) + D = 0
-      // 
-      // and
-      // 
-      // ((-l*A * ab^2 ) / (2 * m))^2/ab^2 + (((1 - l*B) * ab^2) / ( 2 * m))^2/ab^2 + ((-l*C * c^2)/ (2 * m))^2/c^2 - 1 = 0
-      // 
-      // Simple: solve for l and m, then find y from it.
-      // 
-      // (a) Use first equation to find l in terms of m.
-      // 
-      // A * ((-l*A * ab^2 ) / (2 * m)) + B * (((1 - l*B) * ab^2) / ( 2 * m)) + C * ((-l*C * c^2)/ (2 * m)) + D = 0
-      // A * (-l*A * ab^2 ) + B * ((1-l*B) * ab^2) + C * (-l*C * c^2) + D * 2 * m = 0
-      // -A^2*l*ab^2 + B*ab^2 - l*B^2*ab^2 - C^2*l*c^2 + D*2*m = 0
-      // - l *(A^2* ab^2 + B^2 * ab^2 + C^2 * c^2) + (B * ab^2 + D * 2 * m) = 0
-      // l = (B * ab^2 + D * 2 * m) / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2)
-      // l = B * ab^2 / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2) + m * 2 * D / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2)
-      // 
-      // For convenience:
-      // 
-      // k = 1.0 / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2)
-      // 
-      // Then:
-      // 
-      // l = B * ab^2 * k + m * 2 * D * k
-      // l = k * (B*ab^2 + m*2*D)
-      //
-      // For further convenience:
-      //
-      // q = B*ab^2*k
-      // r = 2*D*k
-      //
-      // l = (r*m + q)
-      // l^2 = (r^2 * m^2 + 2*r*m*q + q^2)
-      // 
-      // (b) Simplify the second equation before substitution
-      // 
-      // ((-l*A * ab^2 ) / (2 * m))^2/ab^2 + (((1 - l*B) * ab^2) / ( 2 * m))^2/ab^2 + ((-l*C * c^2)/ (2 * m))^2/c^2 - 1 = 0
-      // (-l*A * ab^2 )^2/ab^2 + ((1 - l*B) * ab^2)^2/ab^2 + (-l*C * c^2)^2/c^2 = 4 * m^2
-      // (-l*A)^2 * ab^2 + (1 - l*B)^2 * ab^2 + (-l*C)^2 * c^2 = 4 * m^2
-      // l^2*A^2 * ab^2 + (1 - 2*l*B + l^2*B^2) * ab^2 + l^2*C^2 * c^2 = 4 * m^2
-      // A^2*ab^2*l^2 + ab^2 - 2*B*ab^2*l + B^2*ab^2*l^2 + C^2*c^2*l^2 - 4*m^2 = 0
-      // 
-      // (c) Substitute for l, l^2
-      //
-      // A^2*ab^2*(r^2 * m^2 + 2*r*m*q + q^2) + ab^2 - 2*B*ab^2*(r*m + q) + B^2*ab^2*(r^2 * m^2 + 2*r*m*q + q^2) + C^2*c^2*(r^2 * m^2 + 2*r*m*q + q^2) - 4*m^2 = 0
-      // A^2*ab^2*r^2*m^2 + 2*A^2*ab^2*r*q*m + A^2*ab^2*q^2 + ab^2 - 2*B*ab^2*r*m - 2*B*ab^2*q + B^2*ab^2*r^2*m^2 +
-      //    2*B^2*ab^2*r*q*m + B^2*ab^2*q^2 + C^2*c^2*r^2*m^2 + 2*C^2*c^2*r*q*m + C^2*c^2*q^2 - 4*m^2 = 0
-      //
-      // (d) Group
-      //
-      // m^2 * [A^2*ab^2*r^2 + B^2*ab^2*r^2 + C^2*c^2*r^2 - 4] +
-      // m * [2*A^2*ab^2*r*q - 2*B*ab^2*r + 2*B^2*ab^2*r*q + 2*C^2*c^2*r*q] +
-      // [A^2*ab^2*q^2 + ab^2 - 2*B*ab^2*q + B^2*ab^2*q^2 + C^2*c^2*q^2]  =  0
-
-      //System.err.println("    computing Y bound");
-      
-      // Useful subexpressions for this bound
-      final double q = B*abSquared*k;
-      final double qSquared = q * q;
-
-      // Quadratic equation
-      final double a = ASquared*abSquared*rSquared + BSquared*abSquared*rSquared + CSquared*cSquared*rSquared - 4.0;
-      final double b = 2.0*ASquared*abSquared*r*q - 2.0*B*abSquared*r + 2.0*BSquared*abSquared*r*q + 2.0*CSquared*cSquared*r*q;
-      final double c = ASquared*abSquared*qSquared + abSquared - 2.0*B*abSquared*q + BSquared*abSquared*qSquared + CSquared*cSquared*qSquared;
-
-      if (Math.abs(a) >= MINIMUM_RESOLUTION_SQUARED) {
-        final double sqrtTerm = b*b - 4.0*a*c;
-        if (Math.abs(sqrtTerm) < MINIMUM_RESOLUTION_SQUARED) {
-          // One solution
-          final double m = -b / (2.0 * a);
-          final double l = r * m + q;
-          // x = (-l*A * ab^2 ) / (2 * m)
-          // y = ((1.0-l*B) * ab^2) / ( 2 * m)
-          // z = (-l*C * c^2)/ (2 * m)
-          final double denom0 = 0.5 / m;
-          final GeoPoint thePoint = new GeoPoint(-l*A * abSquared * denom0, (1.0-l*B) * abSquared * denom0, -l*C * cSquared * denom0);
-          //Math is not quite accurate enough for this
-          //assert planetModel.pointOnSurface(thePoint): "Point: "+thePoint+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
-          //  (thePoint1.x*thePoint.x*planetModel.inverseAb*planetModel.inverseAb + thePoint.y*thePoint.y*planetModel.inverseAb*planetModel.inverseAb + thePoint.z*thePoint.z*planetModel.inverseC*planetModel.inverseC);
-          //assert evaluateIsZero(thePoint): "Evaluation of point: "+evaluate(thePoint);
-          addPoint(boundsInfo, bounds, thePoint);
-        } else if (sqrtTerm > 0.0) {
-          // Two solutions
-          final double sqrtResult = Math.sqrt(sqrtTerm);
-          final double commonDenom = 0.5/a;
-          final double m1 = (-b + sqrtResult) * commonDenom;
-          assert Math.abs(a * m1 * m1 + b * m1 + c) < MINIMUM_RESOLUTION;
-          final double m2 = (-b - sqrtResult) * commonDenom;
-          assert Math.abs(a * m2 * m2 + b * m2 + c) < MINIMUM_RESOLUTION;
-          final double l1 = r * m1 + q;
-          final double l2 = r * m2 + q;
-          // x = (-l*A * ab^2 ) / (2 * m)
-          // y = ((1.0-l*B) * ab^2) / ( 2 * m)
-          // z = (-l*C * c^2)/ (2 * m)
-          final double denom1 = 0.5 / m1;
-          final double denom2 = 0.5 / m2;
-          final GeoPoint thePoint1 = new GeoPoint(-l1*A * abSquared * denom1, (1.0-l1*B) * abSquared * denom1, -l1*C * cSquared * denom1);
-          final GeoPoint thePoint2 = new GeoPoint(-l2*A * abSquared * denom2, (1.0-l2*B) * abSquared * denom2, -l2*C * cSquared * denom2);
-          //Math is not quite accurate enough for this
-          //assert planetModel.pointOnSurface(thePoint1): "Point1: "+thePoint1+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
-          //  (thePoint1.x*thePoint1.x*planetModel.inverseAb*planetModel.inverseAb + thePoint1.y*thePoint1.y*planetModel.inverseAb*planetModel.inverseAb + thePoint1.z*thePoint1.z*planetModel.inverseC*planetModel.inverseC);
-          //assert planetModel.pointOnSurface(thePoint2): "Point2: "+thePoint2+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
-          //  (thePoint2.x*thePoint2.x*planetModel.inverseAb*planetModel.inverseAb + thePoint2.y*thePoint2.y*planetModel.inverseAb*planetModel.inverseAb + thePoint2.z*thePoint2.z*planetModel.inverseC*planetModel.inverseC);
-          //assert evaluateIsZero(thePoint1): "Evaluation of point1: "+evaluate(thePoint1);
-          //assert evaluateIsZero(thePoint2): "Evaluation of point2: "+evaluate(thePoint2);
-          addPoint(boundsInfo, bounds, thePoint1);
-          addPoint(boundsInfo, bounds, thePoint2);
-        } else {
-          // No solutions
-        }
-      } else if (Math.abs(b) > MINIMUM_RESOLUTION_SQUARED) {
-        // a = 0, so m = - c / b
-        final double m = -c / b;
-        final double l = r * m + q;
-        // x = ( -l*A * ab^2 ) / (2 * m)
-        // y = ((1-l*B) * ab^2) / ( 2 * m)
-        // z = (-l*C * c^2)/ (2 * m)
-        final double denom0 = 0.5 / m;
-        final GeoPoint thePoint = new GeoPoint(-l*A * abSquared * denom0, (1.0-l*B) * abSquared * denom0, -l*C * cSquared * denom0);
-        //Math is not quite accurate enough for this
-        //assert planetModel.pointOnSurface(thePoint): "Point: "+thePoint+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
-        //  (thePoint.x*thePoint.x*planetModel.inverseAb*planetModel.inverseAb + thePoint.y*thePoint.y*planetModel.inverseAb*planetModel.inverseAb + thePoint.z*thePoint.z*planetModel.inverseC*planetModel.inverseC);
-        //assert evaluateIsZero(thePoint): "Evaluation of point: "+evaluate(thePoint);
-        addPoint(boundsInfo, bounds, thePoint);
-      } else {
-        // Something went very wrong; a = b = 0
-      }
-    }
-  }
-  
-  /**
-   * Accumulate bounds information for this plane, intersected with the unit sphere.
-   * Updates both latitude and longitude information, using max/min points found
-   * within the specified bounds.
-   *
-   * @param planetModel is the planet model to use in determining bounds.
-   * @param boundsInfo is the lat/lon info to update with additional bounding information.
-   * @param bounds     are the surfaces delineating what's inside the shape.
-   */
-  public void recordBounds(final PlanetModel planetModel, final LatLonBounds boundsInfo, final Membership... bounds) {
-    // For clarity, load local variables with good names
-    final double A = this.x;
-    final double B = this.y;
-    final double C = this.z;
-
-    // Now compute latitude min/max points
-    if (!boundsInfo.checkNoTopLatitudeBound() || !boundsInfo.checkNoBottomLatitudeBound()) {
-      //System.err.println("Looking at latitude for plane "+this);
-      // With ellipsoids, we really have only one viable way to do this computation.
-      // Specifically, we compute an appropriate vertical plane, based on the current plane's x-y orientation, and
-      // then intersect it with this one and with the ellipsoid.  This gives us zero, one, or two points to use
-      // as bounds.
-      // There is one special case: horizontal circles.  These require TWO vertical planes: one for the x, and one for
-      // the y, and we use all four resulting points in the bounds computation.
-      if ((Math.abs(A) >= MINIMUM_RESOLUTION || Math.abs(B) >= MINIMUM_RESOLUTION)) {
-        // NOT a horizontal circle!
-        //System.err.println(" Not a horizontal circle");
-        final Plane verticalPlane = constructNormalizedZPlane(A,B);
-        final GeoPoint[] points = findIntersections(planetModel, verticalPlane, bounds, NO_BOUNDS);
-        for (final GeoPoint point : points) {
-          addPoint(boundsInfo, bounds, point);
-        }
-      } else {
-        // Horizontal circle.  Since a==b, any vertical plane suffices.
-        final GeoPoint[] points = findIntersections(planetModel, normalXPlane, NO_BOUNDS, NO_BOUNDS);
-        boundsInfo.addZValue(points[0]);
-      }
-      //System.err.println("Done latitude bounds");
-    }
-
-    // First, figure out our longitude bounds, unless we no longer need to consider that
-    if (!boundsInfo.checkNoLongitudeBound()) {
-      //System.err.println("Computing longitude bounds for "+this);
-      //System.out.println("A = "+A+" B = "+B+" C = "+C+" D = "+D);
-      // Compute longitude bounds
-
-      double a;
-      double b;
-      double c;
-
-      if (Math.abs(C) < MINIMUM_RESOLUTION) {
-        // Degenerate; the equation describes a line
-        //System.out.println("It's a zero-width ellipse");
-        // Ax + By + D = 0
-        if (Math.abs(D) >= MINIMUM_RESOLUTION) {
-          if (Math.abs(A) > Math.abs(B)) {
-            // Use equation suitable for A != 0
-            // We need to find the endpoints of the zero-width ellipse.
-            // Geometrically, we have a line segment in x-y space.  We need to locate the endpoints
-            // of that line.  But luckily, we know some things: specifically, since it is a
-            // degenerate situation in projection, the C value had to have been 0.  That
-            // means that our line's endpoints will coincide with the projected ellipse.  All we
-            // need to do then is to find the intersection of the projected ellipse and the line
-            // equation:
-            //
-            // A x + B y + D = 0
-            //
-            // Since A != 0:
-            // x = (-By - D)/A
-            //
-            // The projected ellipse:
-            // x^2/a^2 + y^2/b^2 - 1 = 0
-            // Substitute:
-            // [(-By-D)/A]^2/a^2 + y^2/b^2 -1 = 0
-            // Multiply through by A^2:
-            // [-By - D]^2/a^2 + A^2*y^2/b^2 - A^2 = 0
-            // Multiply out:
-            // B^2*y^2/a^2 + 2BDy/a^2 + D^2/a^2 + A^2*y^2/b^2 - A^2 = 0
-            // Group:
-            // y^2 * [B^2/a^2 + A^2/b^2] + y [2BD/a^2] + [D^2/a^2-A^2] = 0
-
-            a = B * B * planetModel.inverseAbSquared + A * A * planetModel.inverseAbSquared;
-            b = 2.0 * B * D * planetModel.inverseAbSquared;
-            c = D * D * planetModel.inverseAbSquared - A * A;
-
-            double sqrtClause = b * b - 4.0 * a * c;
-
-            if (Math.abs(sqrtClause) < MINIMUM_RESOLUTION_SQUARED) {
-              double y0 = -b / (2.0 * a);
-              double x0 = (-D - B * y0) / A;
-              double z0 = 0.0;
-              addPoint(boundsInfo, bounds, new GeoPoint(x0, y0, z0));
-            } else if (sqrtClause > 0.0) {
-              double sqrtResult = Math.sqrt(sqrtClause);
-              double denom = 1.0 / (2.0 * a);
-              double Hdenom = 1.0 / A;
-
-              double y0a = (-b + sqrtResult) * denom;
-              double y0b = (-b - sqrtResult) * denom;
-
-              double x0a = (-D - B * y0a) * Hdenom;
-              double x0b = (-D - B * y0b) * Hdenom;
-
-              double z0a = 0.0;
-              double z0b = 0.0;
-
-              addPoint(boundsInfo, bounds, new GeoPoint(x0a, y0a, z0a));
-              addPoint(boundsInfo, bounds, new GeoPoint(x0b, y0b, z0b));
-            }
-
-          } else {
-            // Use equation suitable for B != 0
-            // Since I != 0, we rewrite:
-            // y = (-Ax - D)/B
-            a = B * B * planetModel.inverseAbSquared + A * A * planetModel.inverseAbSquared;
-            b = 2.0 * A * D * planetModel.inverseAbSquared;
-            c = D * D * planetModel.inverseAbSquared - B * B;
-
-            double sqrtClause = b * b - 4.0 * a * c;
-
-            if (Math.abs(sqrtClause) < MINIMUM_RESOLUTION_SQUARED) {
-              double x0 = -b / (2.0 * a);
-              double y0 = (-D - A * x0) / B;
-              double z0 = 0.0;
-              addPoint(boundsInfo, bounds, new GeoPoint(x0, y0, z0));
-            } else if (sqrtClause > 0.0) {
-              double sqrtResult = Math.sqrt(sqrtClause);
-              double denom = 1.0 / (2.0 * a);
-              double Idenom = 1.0 / B;
-
-              double x0a = (-b + sqrtResult) * denom;
-              double x0b = (-b - sqrtResult) * denom;
-              double y0a = (-D - A * x0a) * Idenom;
-              double y0b = (-D - A * x0b) * Idenom;
-              double z0a = 0.0;
-              double z0b = 0.0;
-
-              addPoint(boundsInfo, bounds, new GeoPoint(x0a, y0a, z0a));
-              addPoint(boundsInfo, bounds, new GeoPoint(x0b, y0b, z0b));
-            }
-          }
-        }
-
-      } else {
-        //System.err.println("General longitude bounds...");
-
-        // NOTE WELL: The x,y,z values generated here are NOT on the unit sphere.
-        // They are for lat/lon calculation purposes only.  x-y is meant to be used for longitude determination,
-        // and z for latitude, and that's all the values are good for.
-
-        // (1) Intersect the plane and the ellipsoid, and project the results into the x-y plane:
-        // From plane:
-        // z = (-Ax - By - D) / C
-        // From ellipsoid:
-        // x^2/a^2 + y^2/b^2 + [(-Ax - By - D) / C]^2/c^2 = 1
-        // Simplify/expand:
-        // C^2*x^2/a^2 + C^2*y^2/b^2 + (-Ax - By - D)^2/c^2 = C^2
-        //
-        // x^2 * C^2/a^2 + y^2 * C^2/b^2 + x^2 * A^2/c^2 + ABxy/c^2 + ADx/c^2 + ABxy/c^2 + y^2 * B^2/c^2 + BDy/c^2 + ADx/c^2 + BDy/c^2 + D^2/c^2 = C^2
-        // Group:
-        // [A^2/c^2 + C^2/a^2] x^2 + [B^2/c^2 + C^2/b^2] y^2 + [2AB/c^2]xy + [2AD/c^2]x + [2BD/c^2]y + [D^2/c^2-C^2] = 0
-        // For convenience, introduce post-projection coefficient variables to make life easier.
-        // E x^2 + F y^2 + G xy + H x + I y + J = 0
-        double E = A * A * planetModel.inverseCSquared + C * C * planetModel.inverseAbSquared;
-        double F = B * B * planetModel.inverseCSquared + C * C * planetModel.inverseAbSquared;
-        double G = 2.0 * A * B * planetModel.inverseCSquared;
-        double H = 2.0 * A * D * planetModel.inverseCSquared;
-        double I = 2.0 * B * D * planetModel.inverseCSquared;
-        double J = D * D * planetModel.inverseCSquared - C * C;
-
-        //System.err.println("E = " + E + " F = " + F + " G = " + G + " H = "+ H + " I = " + I + " J = " + J);
-
-        // Check if the origin is within, by substituting x = 0, y = 0 and seeing if less than zero
-        if (Math.abs(J) >= MINIMUM_RESOLUTION && J > 0.0) {
-          // The derivative of the curve above is:
-          // 2Exdx + 2Fydy + G(xdy+ydx) + Hdx + Idy = 0
-          // (2Ex + Gy + H)dx + (2Fy + Gx + I)dy = 0
-          // dy/dx = - (2Ex + Gy + H) / (2Fy + Gx + I)
-          //
-          // The equation of a line going through the origin with the slope dy/dx is:
-          // y = dy/dx x
-          // y = - (2Ex + Gy + H) / (2Fy + Gx + I)  x
-          // Rearrange:
-          // (2Fy + Gx + I) y + (2Ex + Gy + H) x = 0
-          // 2Fy^2 + Gxy + Iy + 2Ex^2 + Gxy + Hx = 0
-          // 2Ex^2 + 2Fy^2 + 2Gxy + Hx + Iy = 0
-          //
-          // Multiply the original equation by 2:
-          // 2E x^2 + 2F y^2 + 2G xy + 2H x + 2I y + 2J = 0
-          // Subtract one from the other, to remove the high-order terms:
-          // Hx + Iy + 2J = 0
-          // Now, we can substitute either x = or y = into the derivative equation, or into the original equation.
-          // But we will need to base this on which coefficient is non-zero
-
-          if (Math.abs(H) > Math.abs(I)) {
-            //System.err.println(" Using the y quadratic");
-            // x = (-2J - Iy)/H
-
-            // Plug into the original equation:
-            // E [(-2J - Iy)/H]^2 + F y^2 + G [(-2J - Iy)/H]y + H [(-2J - Iy)/H] + I y + J = 0
-            // E [(-2J - Iy)/H]^2 + F y^2 + G [(-2J - Iy)/H]y - J = 0
-            // Same equation as derivative equation, except for a factor of 2!  So it doesn't matter which we pick.
-
-            // Plug into derivative equation:
-            // 2E[(-2J - Iy)/H]^2 + 2Fy^2 + 2G[(-2J - Iy)/H]y + H[(-2J - Iy)/H] + Iy = 0
-            // 2E[(-2J - Iy)/H]^2 + 2Fy^2 + 2G[(-2J - Iy)/H]y - 2J = 0
-            // E[(-2J - Iy)/H]^2 + Fy^2 + G[(-2J - Iy)/H]y - J = 0
-
-            // Multiply by H^2 to make manipulation easier
-            // E[(-2J - Iy)]^2 + F*H^2*y^2 + GH[(-2J - Iy)]y - J*H^2 = 0
-            // Do the square
-            // E[4J^2 + 4IJy + I^2*y^2] + F*H^2*y^2 + GH(-2Jy - I*y^2) - J*H^2 = 0
-
-            // Multiply it out
-            // 4E*J^2 + 4EIJy + E*I^2*y^2 + H^2*Fy^2 - 2GHJy - GH*I*y^2 - J*H^2 = 0
-            // Group:
-            // y^2 [E*I^2 - GH*I + F*H^2] + y [4EIJ - 2GHJ] + [4E*J^2 - J*H^2] = 0
-
-            a = E * I * I - G * H * I + F * H * H;
-            b = 4.0 * E * I * J - 2.0 * G * H * J;
-            c = 4.0 * E * J * J - J * H * H;
-
-            //System.out.println("a="+a+" b="+b+" c="+c);
-            double sqrtClause = b * b - 4.0 * a * c;
-            //System.out.println("sqrtClause="+sqrtClause);
-
-            if (Math.abs(sqrtClause) < MINIMUM_RESOLUTION_CUBED) {
-              //System.err.println(" One solution");
-              double y0 = -b / (2.0 * a);
-              double x0 = (-2.0 * J - I * y0) / H;
-              double z0 = (-A * x0 - B * y0 - D) / C;
-
-              addPoint(boundsInfo, bounds, new GeoPoint(x0, y0, z0));
-            } else if (sqrtClause > 0.0) {
-              //System.err.println(" Two solutions");
-              double sqrtResult = Math.sqrt(sqrtClause);
-              double denom = 1.0 / (2.0 * a);
-              double Hdenom = 1.0 / H;
-              double Cdenom = 1.0 / C;
-
-              double y0a = (-b + sqrtResult) * denom;
-              double y0b = (-b - sqrtResult) * denom;
-              double x0a = (-2.0 * J - I * y0a) * Hdenom;
-              double x0b = (-2.0 * J - I * y0b) * Hdenom;
-              double z0a = (-A * x0a - B * y0a - D) * Cdenom;
-              double z0b = (-A * x0b - B * y0b - D) * Cdenom;
-
-              addPoint(boundsInfo, bounds, new GeoPoint(x0a, y0a, z0a));
-              addPoint(boundsInfo, bounds, new GeoPoint(x0b, y0b, z0b));
-            }
-
-          } else {
-            //System.err.println(" Using the x quadratic");
-            // y = (-2J - Hx)/I
-
-            // Plug into the original equation:
-            // E x^2 + F [(-2J - Hx)/I]^2 + G x[(-2J - Hx)/I] - J = 0
-
-            // Multiply by I^2 to make manipulation easier
-            // E * I^2 * x^2 + F [(-2J - Hx)]^2 + GIx[(-2J - Hx)] - J * I^2 = 0
-            // Do the square
-            // E * I^2 * x^2 + F [ 4J^2 + 4JHx + H^2*x^2] + GI[(-2Jx - H*x^2)] - J * I^2 = 0
-
-            // Multiply it out
-            // E * I^2 * x^2 + 4FJ^2 + 4FJHx + F*H^2*x^2 - 2GIJx - HGI*x^2 - J * I^2 = 0
-            // Group:
-            // x^2 [E*I^2 - GHI + F*H^2] + x [4FJH - 2GIJ] + [4FJ^2 - J*I^2] = 0
-
-            // E x^2 + F y^2 + G xy + H x + I y + J = 0
-
-            a = E * I * I - G * H * I + F * H * H;
-            b = 4.0 * F * H * J - 2.0 * G * I * J;
-            c = 4.0 * F * J * J - J * I * I;
-
-            //System.out.println("a="+a+" b="+b+" c="+c);
-            double sqrtClause = b * b - 4.0 * a * c;
-            //System.out.println("sqrtClause="+sqrtClause);
-            if (Math.abs(sqrtClause) < MINIMUM_RESOLUTION_CUBED) {
-              //System.err.println(" One solution; sqrt clause was "+sqrtClause);
-              double x0 = -b / (2.0 * a);
-              double y0 = (-2.0 * J - H * x0) / I;
-              double z0 = (-A * x0 - B * y0 - D) / C;
-              // Verify that x&y fulfill the equation
-              // 2Ex^2 + 2Fy^2 + 2Gxy + Hx + Iy = 0
-              addPoint(boundsInfo, bounds, new GeoPoint(x0, y0, z0));
-            } else if (sqrtClause > 0.0) {
-              //System.err.println(" Two solutions");
-              double sqrtResult = Math.sqrt(sqrtClause);
-              double denom = 1.0 / (2.0 * a);
-              double Idenom = 1.0 / I;
-              double Cdenom = 1.0 / C;
-
-              double x0a = (-b + sqrtResult) * denom;
-              double x0b = (-b - sqrtResult) * denom;
-              double y0a = (-2.0 * J - H * x0a) * Idenom;
-              double y0b = (-2.0 * J - H * x0b) * Idenom;
-              double z0a = (-A * x0a - B * y0a - D) * Cdenom;
-              double z0b = (-A * x0b - B * y0b - D) * Cdenom;
-
-              addPoint(boundsInfo, bounds, new GeoPoint(x0a, y0a, z0a));
-              addPoint(boundsInfo, bounds, new GeoPoint(x0b, y0b, z0b));
-            }
-          }
-        }
-      }
-    }
-
-  }
-
-  /** Add a point to boundsInfo if within a specifically bounded area.
-   * @param boundsInfo is the object to be modified.
-   * @param bounds is the area that the point must be within.
-   * @param point is the point.
-   */
-  protected static void addPoint(final Bounds boundsInfo, final Membership[] bounds, final GeoPoint point) {
-    // Make sure the discovered point is within the bounds
-    for (Membership bound : bounds) {
-      if (!bound.isWithin(point))
-        return;
-    }
-    // Add the point
-    boundsInfo.addPoint(point);
-  }
-
-  /** Add a point to boundsInfo if within a specifically bounded area.
-   * @param boundsInfo is the object to be modified.
-   * @param bounds is the area that the point must be within.
-   * @param x is the x value.
-   * @param y is the y value.
-   * @param z is the z value.
-   */
-  /*
-  protected static void addPoint(final Bounds boundsInfo, final Membership[] bounds, final double x, final double y, final double z) {
-    //System.err.println(" Want to add point x="+x+" y="+y+" z="+z);
-    // Make sure the discovered point is within the bounds
-    for (Membership bound : bounds) {
-      if (!bound.isWithin(x, y, z))
-        return;
-    }
-    // Add the point
-    //System.err.println("  point added");
-    //System.out.println("Adding point x="+x+" y="+y+" z="+z);
-    boundsInfo.addPoint(x, y, z);
-  }
-  */
-
-  /**
-   * Determine whether the plane intersects another plane within the
-   * bounds provided.
-   *
-   * @param planetModel is the planet model to use in determining intersection.
-   * @param q                 is the other plane.
-   * @param notablePoints     are points to look at to disambiguate cases when the two planes are identical.
-   * @param moreNotablePoints are additional points to look at to disambiguate cases when the two planes are identical.
-   * @param bounds            is one part of the bounds.
-   * @param moreBounds        are more bounds.
-   * @return true if there's an intersection.
-   */
-  public boolean intersects(final PlanetModel planetModel, final Plane q, final GeoPoint[] notablePoints, final GeoPoint[] moreNotablePoints, final Membership[] bounds, final Membership... moreBounds) {
-    //System.err.println("Does plane "+this+" intersect with plane "+q);
-    // If the two planes are identical, then the math will find no points of intersection.
-    // So a special case of this is to check for plane equality.  But that is not enough, because
-    // what we really need at that point is to determine whether overlap occurs between the two parts of the intersection
-    // of plane and circle.  That is, are there *any* points on the plane that are within the bounds described?
-    if (isNumericallyIdentical(q)) {
-      //System.err.println(" Identical plane");
-      // The only way to efficiently figure this out will be to have a list of trial points available to evaluate.
-      // We look for any point that fulfills all the bounds.
-      for (GeoPoint p : notablePoints) {
-        if (meetsAllBounds(p, bounds, moreBounds)) {
-          //System.err.println("  found a notable point in bounds, so intersects");
-          return true;
-        }
-      }
-      for (GeoPoint p : moreNotablePoints) {
-        if (meetsAllBounds(p, bounds, moreBounds)) {
-          //System.err.println("  found a notable point in bounds, so intersects");
-          return true;
-        }
-      }
-      //System.err.println("  no notable points inside found; no intersection");
-      return false;
-    }
-    return findIntersections(planetModel, q, bounds, moreBounds).length > 0;
-  }
-
-  /**
-   * Returns true if this plane and the other plane are identical within the margin of error.
-   * @param p is the plane to compare against.
-   * @return true if the planes are numerically identical.
-   */
-  protected boolean isNumericallyIdentical(final Plane p) {
-    // We can get the correlation by just doing a parallel plane check.  If that passes, then compute a point on the plane
-    // (using D) and see if it also on the other plane.
-    if (Math.abs(this.y * p.z - this.z * p.y) >= MINIMUM_RESOLUTION)
-      return false;
-    if (Math.abs(this.z * p.x - this.x * p.z) >= MINIMUM_RESOLUTION)
-      return false;
-    if (Math.abs(this.x * p.y - this.y * p.x) >= MINIMUM_RESOLUTION)
-      return false;
-
-    // Now, see whether the parallel planes are in fact on top of one another.
-    // The math:
-    // We need a single point that fulfills:
-    // Ax + By + Cz + D = 0
-    // Pick:
-    // x0 = -(A * D) / (A^2 + B^2 + C^2)
-    // y0 = -(B * D) / (A^2 + B^2 + C^2)
-    // z0 = -(C * D) / (A^2 + B^2 + C^2)
-    // Check:
-    // A (x0) + B (y0) + C (z0) + D =? 0
-    // A (-(A * D) / (A^2 + B^2 + C^2)) + B (-(B * D) / (A^2 + B^2 + C^2)) + C (-(C * D) / (A^2 + B^2 + C^2)) + D ?= 0
-    // -D [ A^2 / (A^2 + B^2 + C^2) + B^2 / (A^2 + B^2 + C^2) + C^2 / (A^2 + B^2 + C^2)] + D ?= 0
-    // Yes.
-    final double denom = 1.0 / (p.x * p.x + p.y * p.y + p.z * p.z);
-    return evaluateIsZero(-p.x * p.D * denom, -p.y * p.D * denom, -p.z * p.D * denom);
-  }
-
-  /**
-   * Check if a vector meets the provided bounds.
-   * @param p is the vector.
-   * @param bounds are the bounds.
-   * @return true if the vector describes a point within the bounds.
-   */
-  protected static boolean meetsAllBounds(final Vector p, final Membership[] bounds) {
-    return meetsAllBounds(p.x, p.y, p.z, bounds);
-  }
-
-  /**
-   * Check if a vector meets the provided bounds.
-   * @param x is the x value.
-   * @param y is the y value.
-   * @param z is the z value.
-   * @param bounds are the bounds.
-   * @return true if the vector describes a point within the bounds.
-   */
-  protected static boolean meetsAllBounds(final double x, final double y, final double z, final Membership[] bounds) {
-    for (final Membership bound : bounds) {
-      if (!bound.isWithin(x,y,z))
-        return false;
-    }
-    return true;
-  }
-
-  /**
-   * Check if a vector meets the provided bounds.
-   * @param p is the vector.
-   * @param bounds are the bounds.
-   * @param moreBounds are an additional set of bounds.
-   * @return true if the vector describes a point within the bounds.
-   */
-  protected static boolean meetsAllBounds(final Vector p, final Membership[] bounds, final Membership[] moreBounds) {
-    return meetsAllBounds(p.x, p.y, p.z, bounds, moreBounds);
-  }
-
-  /**
-   * Check if a vector meets the provided bounds.
-   * @param x is the x value.
-   * @param y is the y value.
-   * @param z is the z value.
-   * @param bounds are the bounds.
-   * @param moreBounds are an additional set of bounds.
-   * @return true if the vector describes a point within the bounds.
-   */
-  protected static boolean meetsAllBounds(final double x, final double y, final double z, final Membership[] bounds,
-                                          final Membership[] moreBounds) {
-    return meetsAllBounds(x,y,z, bounds) && meetsAllBounds(x,y,z, moreBounds);
-  }
-
-  /**
-   * Find a sample point on the intersection between two planes and the world.
-   * @param planetModel is the planet model.
-   * @param q is the second plane to consider.
-   * @return a sample point that is on the intersection between the two planes and the world.
-   */
-  public GeoPoint getSampleIntersectionPoint(final PlanetModel planetModel, final Plane q) {
-    final GeoPoint[] intersections = findIntersections(planetModel, q, NO_BOUNDS, NO_BOUNDS);
-    if (intersections.length == 0)
-      return null;
-    return intersections[0];
-  }
-
-  @Override
-  public String toString() {
-    return "[A=" + x + ", B=" + y + "; C=" + z + "; D=" + D + "]";
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!super.equals(o))
-      return false;
-    if (!(o instanceof Plane))
-      return false;
-    Plane other = (Plane) o;
-    return other.D == D;
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    long temp;
-    temp = Double.doubleToLongBits(D);
-    result = 31 * result + (int) (temp ^ (temp >>> 32));
-    return result;
-  }
-}


[28/50] [abbrv] lucene-solr git commit: LUCENE-7077: fail precommit on useless assignment

Posted by no...@apache.org.
LUCENE-7077: fail precommit on useless assignment


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

Branch: refs/heads/apiv2
Commit: bfd58bc9defc85fd4669885329dbfd259fcc118a
Parents: 5bb072d
Author: Robert Muir <rm...@apache.org>
Authored: Tue Mar 8 06:42:35 2016 -0500
Committer: Robert Muir <rm...@apache.org>
Committed: Tue Mar 8 06:42:35 2016 -0500

----------------------------------------------------------------------
 .../src/java/org/apache/lucene/codecs/memory/FSTTermsWriter.java   | 2 +-
 lucene/tools/javadoc/ecj.javadocs.prefs                            | 2 +-
 .../src/test/org/apache/solr/update/DirectUpdateHandlerTest.java   | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/bfd58bc9/lucene/codecs/src/java/org/apache/lucene/codecs/memory/FSTTermsWriter.java
----------------------------------------------------------------------
diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/memory/FSTTermsWriter.java b/lucene/codecs/src/java/org/apache/lucene/codecs/memory/FSTTermsWriter.java
index 50044f1..8284d74 100644
--- a/lucene/codecs/src/java/org/apache/lucene/codecs/memory/FSTTermsWriter.java
+++ b/lucene/codecs/src/java/org/apache/lucene/codecs/memory/FSTTermsWriter.java
@@ -167,7 +167,7 @@ public class FSTTermsWriter extends FieldsConsumer {
       FieldInfo fieldInfo = fieldInfos.fieldInfo(field);
       boolean hasFreq = fieldInfo.getIndexOptions().compareTo(IndexOptions.DOCS_AND_FREQS) >= 0;
       TermsEnum termsEnum = terms.iterator();
-      TermsWriter termsWriter = termsWriter = new TermsWriter(fieldInfo);
+      TermsWriter termsWriter = new TermsWriter(fieldInfo);
 
       long sumTotalTermFreq = 0;
       long sumDocFreq = 0;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/bfd58bc9/lucene/tools/javadoc/ecj.javadocs.prefs
----------------------------------------------------------------------
diff --git a/lucene/tools/javadoc/ecj.javadocs.prefs b/lucene/tools/javadoc/ecj.javadocs.prefs
index 63f22e6..d01148c 100644
--- a/lucene/tools/javadoc/ecj.javadocs.prefs
+++ b/lucene/tools/javadoc/ecj.javadocs.prefs
@@ -51,7 +51,7 @@ org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
 org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
 org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
 org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
-org.eclipse.jdt.core.compiler.problem.noEffectAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
 org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=ignore
 org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
 org.eclipse.jdt.core.compiler.problem.nullReference=ignore

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/bfd58bc9/solr/core/src/test/org/apache/solr/update/DirectUpdateHandlerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/update/DirectUpdateHandlerTest.java b/solr/core/src/test/org/apache/solr/update/DirectUpdateHandlerTest.java
index d35614d..2bde118 100644
--- a/solr/core/src/test/org/apache/solr/update/DirectUpdateHandlerTest.java
+++ b/solr/core/src/test/org/apache/solr/update/DirectUpdateHandlerTest.java
@@ -299,7 +299,7 @@ public class DirectUpdateHandlerTest extends SolrTestCaseJ4 {
     assertU(commit("expungeDeletes","true"));
 
     sr = req("q","foo");
-    r = r = sr.getSearcher().getIndexReader();
+    r = sr.getSearcher().getIndexReader();
     assertEquals(r.maxDoc(), r.numDocs());  // no deletions
     assertEquals(4,r.maxDoc());             // no dups
     sr.close();


[48/50] [abbrv] lucene-solr git commit: LUCENE-7080: Sort files to corrupt to prevent HashSet iteration order issues across JVMs

Posted by no...@apache.org.
LUCENE-7080: Sort files to corrupt to prevent HashSet iteration order issues across JVMs


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

Branch: refs/heads/apiv2
Commit: 588aeeaab731f34af9063ec0dedb714f8740e0b2
Parents: 12f7ad6
Author: Simon Willnauer <si...@apache.org>
Authored: Wed Mar 9 10:56:13 2016 +0100
Committer: Simon Willnauer <si...@apache.org>
Committed: Wed Mar 9 10:56:13 2016 +0100

----------------------------------------------------------------------
 .../java/org/apache/lucene/store/MockDirectoryWrapper.java    | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/588aeeaa/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java b/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java
index 962062e..7fe7c3b 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/store/MockDirectoryWrapper.java
@@ -45,6 +45,7 @@ import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.NoDeletionPolicy;
 import org.apache.lucene.index.SegmentInfos;
+import org.apache.lucene.util.CollectionUtil;
 import org.apache.lucene.util.IOUtils;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestUtil;
@@ -296,7 +297,11 @@ public class MockDirectoryWrapper extends BaseDirectoryWrapper {
   public synchronized void corruptFiles(Collection<String> files) throws IOException {
     // Must make a copy because we change the incoming unsyncedFiles
     // when we create temp files, delete, etc., below:
-    for(String name : new ArrayList<>(files)) {
+    final List<String> filesToCorrupt = new ArrayList<>(files);
+    // sort the files otherwise we have reproducibility issues
+    // across JVMs if the incoming collection is a hashSet etc.
+    CollectionUtil.timSort(filesToCorrupt);
+    for(String name : filesToCorrupt) {
       int damage = randomState.nextInt(6);
       String action = null;
 


[11/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/SidedPlane.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/SidedPlane.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/SidedPlane.java
new file mode 100755
index 0000000..e080bc0
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/SidedPlane.java
@@ -0,0 +1,175 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Combination of a plane, and a sign value indicating what evaluation values are on the correct
+ * side of the plane.
+ *
+ * @lucene.experimental
+ */
+public class SidedPlane extends Plane implements Membership {
+  /** The sign value for evaluation of a point on the correct side of the plane */
+  public final double sigNum;
+
+  /**
+   * Construct a SidedPlane identical to an existing one, but reversed.
+   *
+   * @param sidedPlane is the existing plane.
+   */
+  public SidedPlane(SidedPlane sidedPlane) {
+    super(sidedPlane, sidedPlane.D);
+    this.sigNum = -sidedPlane.sigNum;
+  }
+
+  /**
+   * Construct a sided plane from a pair of vectors describing points, and including
+   * origin, plus a point p which describes the side.
+   *
+   * @param p point to evaluate
+   * @param A is the first in-plane point
+   * @param B is the second in-plane point
+   */
+  public SidedPlane(Vector p, Vector A, Vector B) {
+    super(A, B);
+    sigNum = Math.signum(evaluate(p));
+    if (sigNum == 0.0)
+      throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
+  }
+
+  /**
+   * Construct a sided plane from a point and a Z coordinate.
+   *
+   * @param p      point to evaluate.
+   * @param planetModel is the planet model.
+   * @param sinLat is the sin of the latitude of the plane.
+   */
+  public SidedPlane(Vector p, final PlanetModel planetModel, double sinLat) {
+    super(planetModel, sinLat);
+    sigNum = Math.signum(evaluate(p));
+    if (sigNum == 0.0)
+      throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
+  }
+
+  /**
+   * Construct a sided vertical plane from a point and specified x and y coordinates.
+   *
+   * @param p point to evaluate.
+   * @param x is the specified x.
+   * @param y is the specified y.
+   */
+  public SidedPlane(Vector p, double x, double y) {
+    super(x, y);
+    sigNum = Math.signum(evaluate(p));
+    if (sigNum == 0.0)
+      throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
+  }
+
+  /**
+   * Construct a sided plane with a normal vector and offset.
+   *
+   * @param p point to evaluate.
+   * @param v is the normal vector.
+   * @param D is the origin offset for the plan.
+   */
+  public SidedPlane(Vector p, Vector v, double D) {
+    super(v, D);
+    sigNum = Math.signum(evaluate(p));
+    if (sigNum == 0.0)
+      throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
+  }
+
+  /**
+   * Construct a sided plane with a normal vector and offset.
+   *
+   * @param pX X coord of point to evaluate.
+   * @param pY Y coord of point to evaluate.
+   * @param pZ Z coord of point to evaluate.
+   * @param v is the normal vector.
+   * @param D is the origin offset for the plan.
+   */
+  public SidedPlane(double pX, double pY, double pZ, Vector v, double D) {
+    super(v, D);
+    sigNum = Math.signum(evaluate(pX,pY,pZ));
+    if (sigNum == 0.0)
+      throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
+  }
+
+  /** Construct a sided plane from two points and a third normal vector.
+   */
+  public static SidedPlane constructNormalizedPerpendicularSidedPlane(final Vector insidePoint,
+    final Vector normalVector, final Vector point1, final Vector point2) {
+    final Vector pointsVector = new Vector(point1.x - point2.x, point1.y - point2.y, point1.z - point2.z);
+    final Vector newNormalVector = new Vector(normalVector, pointsVector);
+    try {
+      // To construct the plane, we now just need D, which is simply the negative of the evaluation of the circle normal vector at one of the points.
+      return new SidedPlane(insidePoint, newNormalVector, -newNormalVector.dotProduct(point1));
+    } catch (IllegalArgumentException e) {
+      return null;
+    }
+  }
+  
+  /** Construct a sided plane from three points.
+   */
+  public static SidedPlane constructNormalizedThreePointSidedPlane(final Vector insidePoint,
+    final Vector point1, final Vector point2, final Vector point3) {
+    try {
+      final Vector planeNormal = new Vector(
+        new Vector(point1.x - point2.x, point1.y - point2.y, point1.z - point2.z),
+        new Vector(point2.x - point3.x, point2.y - point3.y, point2.z - point3.z));
+      return new SidedPlane(insidePoint, planeNormal, -planeNormal.dotProduct(point2));
+    } catch (IllegalArgumentException e) {
+      return null;
+    }
+  }
+
+  @Override
+  public boolean isWithin(double x, double y, double z) {
+    double evalResult = evaluate(x, y, z);
+    if (Math.abs(evalResult) < MINIMUM_RESOLUTION)
+      return true;
+    double sigNum = Math.signum(evalResult);
+    return sigNum == this.sigNum;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (!(o instanceof SidedPlane)) return false;
+    if (!super.equals(o)) return false;
+
+    SidedPlane that = (SidedPlane) o;
+
+    return Double.compare(that.sigNum, sigNum) == 0;
+
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    long temp;
+    temp = Double.doubleToLongBits(sigNum);
+    result = 31 * result + (int) (temp ^ (temp >>> 32));
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "[A=" + x + ", B=" + y + ", C=" + z + ", D=" + D + ", side=" + sigNum + "]";
+  }
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/StandardXYZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/StandardXYZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/StandardXYZSolid.java
new file mode 100644
index 0000000..492f7b4
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/StandardXYZSolid.java
@@ -0,0 +1,417 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * 3D rectangle, bounded on six sides by X,Y,Z limits
+ *
+ * @lucene.internal
+ */
+public class StandardXYZSolid extends BaseXYZSolid {
+
+  /** Whole world? */
+  protected final boolean isWholeWorld;
+  /** Min-X plane */
+  protected final SidedPlane minXPlane;
+  /** Max-X plane */
+  protected final SidedPlane maxXPlane;
+  /** Min-Y plane */
+  protected final SidedPlane minYPlane;
+  /** Max-Y plane */
+  protected final SidedPlane maxYPlane;
+  /** Min-Z plane */
+  protected final SidedPlane minZPlane;
+  /** Max-Z plane */
+  protected final SidedPlane maxZPlane;
+  
+  /** These are the edge points of the shape, which are defined to be at least one point on
+   * each surface area boundary.  In the case of a solid, this includes points which represent
+   * the intersection of XYZ bounding planes and the planet, as well as points representing
+   * the intersection of single bounding planes with the planet itself.
+   */
+  protected final GeoPoint[] edgePoints;
+
+  /** Notable points for minXPlane */
+  protected final GeoPoint[] notableMinXPoints;
+  /** Notable points for maxXPlane */
+  protected final GeoPoint[] notableMaxXPoints;
+  /** Notable points for minYPlane */
+  protected final GeoPoint[] notableMinYPoints;
+  /** Notable points for maxYPlane */
+  protected final GeoPoint[] notableMaxYPoints;
+  /** Notable points for minZPlane */
+  protected final GeoPoint[] notableMinZPoints;
+  /** Notable points for maxZPlane */
+  protected final GeoPoint[] notableMaxZPoints;
+
+  /**
+   * Sole constructor
+   *
+   *@param planetModel is the planet model.
+   *@param minX is the minimum X value.
+   *@param maxX is the maximum X value.
+   *@param minY is the minimum Y value.
+   *@param maxY is the maximum Y value.
+   *@param minZ is the minimum Z value.
+   *@param maxZ is the maximum Z value.
+   */
+  public StandardXYZSolid(final PlanetModel planetModel,
+    final double minX,
+    final double maxX,
+    final double minY,
+    final double maxY,
+    final double minZ,
+    final double maxZ) {
+    super(planetModel);
+    // Argument checking
+    if (maxX - minX < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("X values in wrong order or identical");
+    if (maxY - minY < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("Y values in wrong order or identical");
+    if (maxZ - minZ < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("Z values in wrong order or identical");
+
+    final double worldMinX = planetModel.getMinimumXValue();
+    final double worldMaxX = planetModel.getMaximumXValue();
+    final double worldMinY = planetModel.getMinimumYValue();
+    final double worldMaxY = planetModel.getMaximumYValue();
+    final double worldMinZ = planetModel.getMinimumZValue();
+    final double worldMaxZ = planetModel.getMaximumZValue();
+    
+    // We must distinguish between the case where the solid represents the entire world,
+    // and when the solid has no overlap with any part of the surface.  In both cases,
+    // there will be no edgepoints.
+    isWholeWorld =
+        (minX - worldMinX < -Vector.MINIMUM_RESOLUTION) &&
+        (maxX - worldMaxX > Vector.MINIMUM_RESOLUTION) &&
+        (minY - worldMinY < -Vector.MINIMUM_RESOLUTION) &&
+        (maxY - worldMaxY > Vector.MINIMUM_RESOLUTION) &&
+        (minZ - worldMinZ < -Vector.MINIMUM_RESOLUTION) &&
+        (maxZ - worldMaxZ > Vector.MINIMUM_RESOLUTION);
+
+    if (isWholeWorld) {
+      minXPlane = null;
+      maxXPlane = null;
+      minYPlane = null;
+      maxYPlane = null;
+      minZPlane = null;
+      maxZPlane = null;
+      notableMinXPoints = null;
+      notableMaxXPoints = null;
+      notableMinYPoints = null;
+      notableMaxYPoints = null;
+      notableMinZPoints = null;
+      notableMaxZPoints = null;
+      edgePoints = null;
+    } else {
+      // Construct the planes
+      minXPlane = new SidedPlane(maxX,0.0,0.0,xUnitVector,-minX);
+      maxXPlane = new SidedPlane(minX,0.0,0.0,xUnitVector,-maxX);
+      minYPlane = new SidedPlane(0.0,maxY,0.0,yUnitVector,-minY);
+      maxYPlane = new SidedPlane(0.0,minY,0.0,yUnitVector,-maxY);
+      minZPlane = new SidedPlane(0.0,0.0,maxZ,zUnitVector,-minZ);
+      maxZPlane = new SidedPlane(0.0,0.0,minZ,zUnitVector,-maxZ);
+      
+      // We need at least one point on the planet surface for each manifestation of the shape.
+      // There can be up to 2 (on opposite sides of the world).  But we have to go through
+      // 12 combinations of adjacent planes in order to find out if any have 2 intersection solution.
+      // Typically, this requires 12 square root operations. 
+      final GeoPoint[] minXminY = minXPlane.findIntersections(planetModel,minYPlane,maxXPlane,maxYPlane,minZPlane,maxZPlane);
+      final GeoPoint[] minXmaxY = minXPlane.findIntersections(planetModel,maxYPlane,maxXPlane,minYPlane,minZPlane,maxZPlane);
+      final GeoPoint[] minXminZ = minXPlane.findIntersections(planetModel,minZPlane,maxXPlane,maxZPlane,minYPlane,maxYPlane);
+      final GeoPoint[] minXmaxZ = minXPlane.findIntersections(planetModel,maxZPlane,maxXPlane,minZPlane,minYPlane,maxYPlane);
+
+      final GeoPoint[] maxXminY = maxXPlane.findIntersections(planetModel,minYPlane,minXPlane,maxYPlane,minZPlane,maxZPlane);
+      final GeoPoint[] maxXmaxY = maxXPlane.findIntersections(planetModel,maxYPlane,minXPlane,minYPlane,minZPlane,maxZPlane);
+      final GeoPoint[] maxXminZ = maxXPlane.findIntersections(planetModel,minZPlane,minXPlane,maxZPlane,minYPlane,maxYPlane);
+      final GeoPoint[] maxXmaxZ = maxXPlane.findIntersections(planetModel,maxZPlane,minXPlane,minZPlane,minYPlane,maxYPlane);
+      
+      final GeoPoint[] minYminZ = minYPlane.findIntersections(planetModel,minZPlane,maxYPlane,maxZPlane,minXPlane,maxXPlane);
+      final GeoPoint[] minYmaxZ = minYPlane.findIntersections(planetModel,maxZPlane,maxYPlane,minZPlane,minXPlane,maxXPlane);
+      final GeoPoint[] maxYminZ = maxYPlane.findIntersections(planetModel,minZPlane,minYPlane,maxZPlane,minXPlane,maxXPlane);
+      final GeoPoint[] maxYmaxZ = maxYPlane.findIntersections(planetModel,maxZPlane,minYPlane,minZPlane,minXPlane,maxXPlane);
+      
+      notableMinXPoints = glueTogether(minXminY, minXmaxY, minXminZ, minXmaxZ);
+      notableMaxXPoints = glueTogether(maxXminY, maxXmaxY, maxXminZ, maxXmaxZ);
+      notableMinYPoints = glueTogether(minXminY, maxXminY, minYminZ, minYmaxZ);
+      notableMaxYPoints = glueTogether(minXmaxY, maxXmaxY, maxYminZ, maxYmaxZ);
+      notableMinZPoints = glueTogether(minXminZ, maxXminZ, minYminZ, maxYminZ);
+      notableMaxZPoints = glueTogether(minXmaxZ, maxXmaxZ, minYmaxZ, maxYmaxZ);
+
+      // Now, compute the edge points.
+      // This is the trickiest part of setting up an XYZSolid.  We've computed intersections already, so
+      // we'll start there.
+      // There can be a number of shapes, each of which needs an edgepoint.  Each side by itself might contribute
+      // an edgepoint, for instance, if the plane describing that side intercepts the planet in such a way that the ellipse
+      // of interception does not meet any other planes.  Plane intersections can each contribute 0, 1, or 2 edgepoints.
+      //
+      // All of this makes for a lot of potential edgepoints, but I believe these can be pruned back with careful analysis.
+      // I haven't yet done that analysis, however, so I will treat them all as individual edgepoints.
+      
+      // The cases we are looking for are when the four corner points for any given
+      // plane are all outside of the world, AND that plane intersects the world.
+      // There are eight corner points all told; we must evaluate these WRT the planet surface.
+      final boolean minXminYminZ = planetModel.pointOutside(minX, minY, minZ);
+      final boolean minXminYmaxZ = planetModel.pointOutside(minX, minY, maxZ);
+      final boolean minXmaxYminZ = planetModel.pointOutside(minX, maxY, minZ);
+      final boolean minXmaxYmaxZ = planetModel.pointOutside(minX, maxY, maxZ);
+      final boolean maxXminYminZ = planetModel.pointOutside(maxX, minY, minZ);
+      final boolean maxXminYmaxZ = planetModel.pointOutside(maxX, minY, maxZ);
+      final boolean maxXmaxYminZ = planetModel.pointOutside(maxX, maxY, minZ);
+      final boolean maxXmaxYmaxZ = planetModel.pointOutside(maxX, maxY, maxZ);
+        
+      // Look at single-plane/world intersections.
+      // We detect these by looking at the world model and noting its x, y, and z bounds.
+
+      final GeoPoint[] minXEdges;
+      if (minX - worldMinX >= -Vector.MINIMUM_RESOLUTION && minX - worldMaxX <= Vector.MINIMUM_RESOLUTION &&
+        minY < 0.0 && maxY > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
+        minXminYminZ && minXminYmaxZ && minXmaxYminZ && minXmaxYmaxZ) {
+        // Find any point on the minX plane that intersects the world
+        // First construct a perpendicular plane that will allow us to find a sample point.
+        // This plane is vertical and goes through the points (0,0,0) and (1,0,0)
+        // Then use it to compute a sample point.
+        final GeoPoint intPoint = minXPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
+        if (intPoint != null) {
+          minXEdges = new GeoPoint[]{intPoint};
+        } else {
+          // No intersection found?
+          minXEdges = EMPTY_POINTS;
+        }
+      } else {
+        minXEdges = EMPTY_POINTS;
+      }
+      
+      final GeoPoint[] maxXEdges;
+      if (maxX - worldMinX >= -Vector.MINIMUM_RESOLUTION && maxX - worldMaxX <= Vector.MINIMUM_RESOLUTION &&
+        minY < 0.0 && maxY > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
+        maxXminYminZ && maxXminYmaxZ && maxXmaxYminZ && maxXmaxYmaxZ) {
+        // Find any point on the maxX plane that intersects the world
+        // First construct a perpendicular plane that will allow us to find a sample point.
+        // This plane is vertical and goes through the points (0,0,0) and (1,0,0)
+        // Then use it to compute a sample point.
+        final GeoPoint intPoint = maxXPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
+        if (intPoint != null) {
+          maxXEdges = new GeoPoint[]{intPoint};
+        } else {
+          maxXEdges = EMPTY_POINTS;
+        }
+      } else {
+        maxXEdges = EMPTY_POINTS;
+      }
+      
+      final GeoPoint[] minYEdges;
+      if (minY - worldMinY >= -Vector.MINIMUM_RESOLUTION && minY - worldMaxY <= Vector.MINIMUM_RESOLUTION &&
+        minX < 0.0 && maxX > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
+        minXminYminZ && minXminYmaxZ && maxXminYminZ && maxXminYmaxZ) {
+        // Find any point on the minY plane that intersects the world
+        // First construct a perpendicular plane that will allow us to find a sample point.
+        // This plane is vertical and goes through the points (0,0,0) and (0,1,0)
+        // Then use it to compute a sample point.
+        final GeoPoint intPoint = minYPlane.getSampleIntersectionPoint(planetModel, yVerticalPlane);
+        if (intPoint != null) {
+          minYEdges = new GeoPoint[]{intPoint};
+        } else {
+          minYEdges = EMPTY_POINTS;
+        }
+      } else {
+        minYEdges = EMPTY_POINTS;
+      }
+      
+      final GeoPoint[] maxYEdges;
+      if (maxY - worldMinY >= -Vector.MINIMUM_RESOLUTION && maxY - worldMaxY <= Vector.MINIMUM_RESOLUTION &&
+        minX < 0.0 && maxX > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
+        minXmaxYminZ && minXmaxYmaxZ && maxXmaxYminZ && maxXmaxYmaxZ) {
+        // Find any point on the maxY plane that intersects the world
+        // First construct a perpendicular plane that will allow us to find a sample point.
+        // This plane is vertical and goes through the points (0,0,0) and (0,1,0)
+        // Then use it to compute a sample point.
+        final GeoPoint intPoint = maxYPlane.getSampleIntersectionPoint(planetModel, yVerticalPlane);
+        if (intPoint != null) {
+          maxYEdges = new GeoPoint[]{intPoint};
+        } else {
+          maxYEdges = EMPTY_POINTS;
+        }
+      } else {
+        maxYEdges = EMPTY_POINTS;
+      }
+      
+      final GeoPoint[] minZEdges;
+      if (minZ - worldMinZ >= -Vector.MINIMUM_RESOLUTION && minZ - worldMaxZ <= Vector.MINIMUM_RESOLUTION &&
+        minX < 0.0 && maxX > 0.0 && minY < 0.0 && maxY > 0.0 &&
+        minXminYminZ && minXmaxYminZ && maxXminYminZ && maxXmaxYminZ) {
+        // Find any point on the minZ plane that intersects the world
+        // First construct a perpendicular plane that will allow us to find a sample point.
+        // This plane is vertical and goes through the points (0,0,0) and (1,0,0)
+        // Then use it to compute a sample point.
+        final GeoPoint intPoint = minZPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
+        if (intPoint != null) {
+          minZEdges = new GeoPoint[]{intPoint};
+        } else {
+          minZEdges = EMPTY_POINTS;
+        }
+      } else {
+        minZEdges = EMPTY_POINTS;
+      }
+      
+      final GeoPoint[] maxZEdges;
+      if (maxZ - worldMinZ >= -Vector.MINIMUM_RESOLUTION && maxZ - worldMaxZ <= Vector.MINIMUM_RESOLUTION &&
+        minX < 0.0 && maxX > 0.0 && minY < 0.0 && maxY > 0.0 &&
+        minXminYmaxZ && minXmaxYmaxZ && maxXminYmaxZ && maxXmaxYmaxZ) {
+        // Find any point on the maxZ plane that intersects the world
+        // First construct a perpendicular plane that will allow us to find a sample point.
+        // This plane is vertical and goes through the points (0,0,0) and (1,0,0) (that is, its orientation doesn't matter)
+        // Then use it to compute a sample point.
+        final GeoPoint intPoint = maxZPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
+        if (intPoint != null) {
+          maxZEdges = new GeoPoint[]{intPoint};
+        } else {
+          maxZEdges = EMPTY_POINTS;
+        }
+      } else {
+        maxZEdges = EMPTY_POINTS;
+      }
+      
+      // Glue everything together.  This is not a minimal set of edgepoints, as of now, but it does completely describe all shapes on the
+      // planet.
+      this.edgePoints = glueTogether(minXminY, minXmaxY, minXminZ, minXmaxZ,
+        maxXminY, maxXmaxY, maxXminZ, maxXmaxZ,
+        minYminZ, minYmaxZ, maxYminZ, maxYmaxZ,
+        minXEdges, maxXEdges, minYEdges, maxYEdges, minZEdges, maxZEdges);
+    }
+  }
+
+  @Override
+  protected GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+  
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    if (isWholeWorld) {
+      return true;
+    }
+    return minXPlane.isWithin(x, y, z) &&
+      maxXPlane.isWithin(x, y, z) &&
+      minYPlane.isWithin(x, y, z) &&
+      maxYPlane.isWithin(x, y, z) &&
+      minZPlane.isWithin(x, y, z) &&
+      maxZPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    if (isWholeWorld) {
+      if (path.getEdgePoints().length > 0)
+        return WITHIN;
+      return OVERLAPS;
+    }
+    
+    /*
+    for (GeoPoint p : getEdgePoints()) {
+      System.err.println(" Edge point "+p+" path.isWithin()? "+path.isWithin(p));
+    }
+    
+    for (GeoPoint p : path.getEdgePoints()) {
+      System.err.println(" path edge point "+p+" isWithin()? "+isWithin(p)+" minx="+minXPlane.evaluate(p)+" maxx="+maxXPlane.evaluate(p)+" miny="+minYPlane.evaluate(p)+" maxy="+maxYPlane.evaluate(p)+" minz="+minZPlane.evaluate(p)+" maxz="+maxZPlane.evaluate(p));
+    }
+    */
+    
+    //System.err.println(this+" getrelationship with "+path);
+    final int insideRectangle = isShapeInsideArea(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some shape points inside area");
+      return OVERLAPS;
+    }
+
+    // Figure out if the entire XYZArea is contained by the shape.
+    final int insideShape = isAreaInsideShape(path);
+    if (insideShape == SOME_INSIDE) {
+      //System.err.println(" some area points inside shape");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
+      //System.err.println(" inside of each other");
+      return OVERLAPS;
+    }
+
+    if (path.intersects(minXPlane, notableMinXPoints, maxXPlane, minYPlane, maxYPlane, minZPlane, maxZPlane) ||
+        path.intersects(maxXPlane, notableMaxXPoints, minXPlane, minYPlane, maxYPlane, minZPlane, maxZPlane) ||
+        path.intersects(minYPlane, notableMinYPoints, maxYPlane, minXPlane, maxXPlane, minZPlane, maxZPlane) ||
+        path.intersects(maxYPlane, notableMaxYPoints, minYPlane, minXPlane, maxXPlane, minZPlane, maxZPlane) ||
+        path.intersects(minZPlane, notableMinZPoints, maxZPlane, minXPlane, maxXPlane, minYPlane, maxYPlane) ||
+        path.intersects(maxZPlane, notableMaxZPoints, minZPlane, minXPlane, maxXPlane, minYPlane, maxYPlane)) {
+      //System.err.println(" edges intersect");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      //System.err.println(" all shape points inside area");
+      return WITHIN;
+    }
+
+    if (insideShape == ALL_INSIDE) {
+      //System.err.println(" all area points inside shape");
+      return CONTAINS;
+    }
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof StandardXYZSolid))
+      return false;
+    StandardXYZSolid other = (StandardXYZSolid) o;
+    if (!super.equals(other) ||
+      other.isWholeWorld != isWholeWorld) {
+      return false;
+    }
+    if (!isWholeWorld) {
+      return other.minXPlane.equals(minXPlane) &&
+        other.maxXPlane.equals(maxXPlane) &&
+        other.minYPlane.equals(minYPlane) &&
+        other.maxYPlane.equals(maxYPlane) &&
+        other.minZPlane.equals(minZPlane) &&
+        other.maxZPlane.equals(maxZPlane);
+    }
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + (isWholeWorld?1:0);
+    if (!isWholeWorld) {
+      result = 31 * result  + minXPlane.hashCode();
+      result = 31 * result  + maxXPlane.hashCode();
+      result = 31 * result  + minYPlane.hashCode();
+      result = 31 * result  + maxYPlane.hashCode();
+      result = 31 * result  + minZPlane.hashCode();
+      result = 31 * result  + maxZPlane.hashCode();
+    }
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "StandardXYZSolid: {planetmodel="+planetModel+", isWholeWorld="+isWholeWorld+", minXplane="+minXPlane+", maxXplane="+maxXPlane+", minYplane="+minYPlane+", maxYplane="+maxYPlane+", minZplane="+minZPlane+", maxZplane="+maxZPlane+"}";
+  }
+  
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Tools.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Tools.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Tools.java
new file mode 100755
index 0000000..e8ee29e
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Tools.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Static methods globally useful for 3d geometric work.
+ *
+ * @lucene.experimental
+ */
+public class Tools {
+  private Tools() {
+  }
+
+  /**
+   * Java acos yields a NAN if you take an arc-cos of an
+   * angle that's just a tiny bit greater than 1.0, so
+   * here's a more resilient version.
+   */
+  public static double safeAcos(double value) {
+    if (value > 1.0)
+      value = 1.0;
+    else if (value < -1.0)
+      value = -1.0;
+    return Math.acos(value);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Vector.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Vector.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Vector.java
new file mode 100755
index 0000000..3a1b233
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Vector.java
@@ -0,0 +1,378 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * A 3d vector in space, not necessarily
+ * going through the origin.
+ *
+ * @lucene.experimental
+ */
+public class Vector {
+  /**
+   * Values that are all considered to be essentially zero have a magnitude
+   * less than this.
+   */
+  public static final double MINIMUM_RESOLUTION = 1.0e-12;
+  /**
+   * For squared quantities, the bound is squared too.
+   */
+  public static final double MINIMUM_RESOLUTION_SQUARED = MINIMUM_RESOLUTION * MINIMUM_RESOLUTION;
+  /**
+   * For cubed quantities, cube the bound.
+   */
+  public static final double MINIMUM_RESOLUTION_CUBED = MINIMUM_RESOLUTION_SQUARED * MINIMUM_RESOLUTION;
+
+  /** The x value */
+  public final double x;
+  /** The y value */
+  public final double y;
+  /** The z value */
+  public final double z;
+
+  /**
+   * Construct from (U.S.) x,y,z coordinates.
+   *@param x is the x value.
+   *@param y is the y value.
+   *@param z is the z value.
+   */
+  public Vector(double x, double y, double z) {
+    this.x = x;
+    this.y = y;
+    this.z = z;
+  }
+
+  /**
+   * Construct a vector that is perpendicular to
+   * two other (non-zero) vectors.  If the vectors are parallel,
+   * IllegalArgumentException will be thrown.
+   * Produces a normalized final vector.
+   *
+   * @param A is the first vector
+   * @param B is the second
+   */
+  public Vector(final Vector A, final Vector B) {
+    // x = u2v3 - u3v2
+    // y = u3v1 - u1v3
+    // z = u1v2 - u2v1
+    final double thisX = A.y * B.z - A.z * B.y;
+    final double thisY = A.z * B.x - A.x * B.z;
+    final double thisZ = A.x * B.y - A.y * B.x;
+    final double magnitude = magnitude(thisX, thisY, thisZ);
+    if (Math.abs(magnitude) < MINIMUM_RESOLUTION) {
+      throw new IllegalArgumentException("Degenerate/parallel vector constructed");
+    }
+    final double inverseMagnitude = 1.0 / magnitude;
+    this.x = thisX * inverseMagnitude;
+    this.y = thisY * inverseMagnitude;
+    this.z = thisZ * inverseMagnitude;
+  }
+
+  /** Compute a magnitude of an x,y,z value.
+   */
+  public static double magnitude(final double x, final double y, final double z) {
+    return Math.sqrt(x*x + y*y + z*z);
+  }
+  
+  /**
+   * Compute a normalized unit vector based on the current vector.
+   *
+   * @return the normalized vector, or null if the current vector has
+   * a magnitude of zero.
+   */
+  public Vector normalize() {
+    double denom = magnitude();
+    if (denom < MINIMUM_RESOLUTION)
+      // Degenerate, can't normalize
+      return null;
+    double normFactor = 1.0 / denom;
+    return new Vector(x * normFactor, y * normFactor, z * normFactor);
+  }
+
+  /**
+   * Do a dot product.
+   *
+   * @param v is the vector to multiply.
+   * @return the result.
+   */
+  public double dotProduct(final Vector v) {
+    return this.x * v.x + this.y * v.y + this.z * v.z;
+  }
+
+  /**
+   * Do a dot product.
+   *
+   * @param x is the x value of the vector to multiply.
+   * @param y is the y value of the vector to multiply.
+   * @param z is the z value of the vector to multiply.
+   * @return the result.
+   */
+  public double dotProduct(final double x, final double y, final double z) {
+    return this.x * x + this.y * y + this.z * z;
+  }
+
+  /**
+   * Determine if this vector, taken from the origin,
+   * describes a point within a set of planes.
+   *
+   * @param bounds     is the first part of the set of planes.
+   * @param moreBounds is the second part of the set of planes.
+   * @return true if the point is within the bounds.
+   */
+  public boolean isWithin(final Membership[] bounds, final Membership[] moreBounds) {
+    // Return true if the point described is within all provided bounds
+    //System.err.println("  checking if "+this+" is within bounds");
+    for (Membership bound : bounds) {
+      if (bound != null && !bound.isWithin(this)) {
+        //System.err.println("    NOT within "+bound);
+        return false;
+      }
+    }
+    for (Membership bound : moreBounds) {
+      if (bound != null && !bound.isWithin(this)) {
+        //System.err.println("    NOT within "+bound);
+        return false;
+      }
+    }
+    //System.err.println("    is within");
+    return true;
+  }
+
+  /**
+   * Translate vector.
+   */
+  public Vector translate(final double xOffset, final double yOffset, final double zOffset) {
+    return new Vector(x - xOffset, y - yOffset, z - zOffset);
+  }
+
+  /**
+   * Rotate vector counter-clockwise in x-y by an angle.
+   */
+  public Vector rotateXY(final double angle) {
+    return rotateXY(Math.sin(angle), Math.cos(angle));
+  }
+
+  /**
+   * Rotate vector counter-clockwise in x-y by an angle, expressed as sin and cos.
+   */
+  public Vector rotateXY(final double sinAngle, final double cosAngle) {
+    return new Vector(x * cosAngle - y * sinAngle, x * sinAngle + y * cosAngle, z);
+  }
+
+  /**
+   * Rotate vector counter-clockwise in x-z by an angle.
+   */
+  public Vector rotateXZ(final double angle) {
+    return rotateXZ(Math.sin(angle), Math.cos(angle));
+  }
+
+  /**
+   * Rotate vector counter-clockwise in x-z by an angle, expressed as sin and cos.
+   */
+  public Vector rotateXZ(final double sinAngle, final double cosAngle) {
+    return new Vector(x * cosAngle - z * sinAngle, y, x * sinAngle + z * cosAngle);
+  }
+
+  /**
+   * Rotate vector counter-clockwise in z-y by an angle.
+   */
+  public Vector rotateZY(final double angle) {
+    return rotateZY(Math.sin(angle), Math.cos(angle));
+  }
+
+  /**
+   * Rotate vector counter-clockwise in z-y by an angle, expressed as sin and cos.
+   */
+  public Vector rotateZY(final double sinAngle, final double cosAngle) {
+    return new Vector(x, z * sinAngle + y * cosAngle, z * cosAngle - y * sinAngle);
+  }
+
+  /**
+   * Compute the square of a straight-line distance to a point described by the
+   * vector taken from the origin.
+   * Monotonically increasing for arc distances up to PI.
+   *
+   * @param v is the vector to compute a distance to.
+   * @return the square of the linear distance.
+   */
+  public double linearDistanceSquared(final Vector v) {
+    double deltaX = this.x - v.x;
+    double deltaY = this.y - v.y;
+    double deltaZ = this.z - v.z;
+    return deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
+  }
+
+  /**
+   * Compute the square of a straight-line distance to a point described by the
+   * vector taken from the origin.
+   * Monotonically increasing for arc distances up to PI.
+   *
+   * @param x is the x part of the vector to compute a distance to.
+   * @param y is the y part of the vector to compute a distance to.
+   * @param z is the z part of the vector to compute a distance to.
+   * @return the square of the linear distance.
+   */
+  public double linearDistanceSquared(final double x, final double y, final double z) {
+    double deltaX = this.x - x;
+    double deltaY = this.y - y;
+    double deltaZ = this.z - z;
+    return deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
+  }
+
+  /**
+   * Compute the straight-line distance to a point described by the
+   * vector taken from the origin.
+   * Monotonically increasing for arc distances up to PI.
+   *
+   * @param v is the vector to compute a distance to.
+   * @return the linear distance.
+   */
+  public double linearDistance(final Vector v) {
+    return Math.sqrt(linearDistanceSquared(v));
+  }
+
+  /**
+   * Compute the straight-line distance to a point described by the
+   * vector taken from the origin.
+   * Monotonically increasing for arc distances up to PI.
+   *
+   * @param x is the x part of the vector to compute a distance to.
+   * @param y is the y part of the vector to compute a distance to.
+   * @param z is the z part of the vector to compute a distance to.
+   * @return the linear distance.
+   */
+  public double linearDistance(final double x, final double y, final double z) {
+    return Math.sqrt(linearDistanceSquared(x, y, z));
+  }
+
+  /**
+   * Compute the square of the normal distance to a vector described by a
+   * vector taken from the origin.
+   * Monotonically increasing for arc distances up to PI/2.
+   *
+   * @param v is the vector to compute a distance to.
+   * @return the square of the normal distance.
+   */
+  public double normalDistanceSquared(final Vector v) {
+    double t = dotProduct(v);
+    double deltaX = this.x * t - v.x;
+    double deltaY = this.y * t - v.y;
+    double deltaZ = this.z * t - v.z;
+    return deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
+  }
+
+  /**
+   * Compute the square of the normal distance to a vector described by a
+   * vector taken from the origin.
+   * Monotonically increasing for arc distances up to PI/2.
+   *
+   * @param x is the x part of the vector to compute a distance to.
+   * @param y is the y part of the vector to compute a distance to.
+   * @param z is the z part of the vector to compute a distance to.
+   * @return the square of the normal distance.
+   */
+  public double normalDistanceSquared(final double x, final double y, final double z) {
+    double t = dotProduct(x, y, z);
+    double deltaX = this.x * t - x;
+    double deltaY = this.y * t - y;
+    double deltaZ = this.z * t - z;
+    return deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
+  }
+
+  /**
+   * Compute the normal (perpendicular) distance to a vector described by a
+   * vector taken from the origin.
+   * Monotonically increasing for arc distances up to PI/2.
+   *
+   * @param v is the vector to compute a distance to.
+   * @return the normal distance.
+   */
+  public double normalDistance(final Vector v) {
+    return Math.sqrt(normalDistanceSquared(v));
+  }
+
+  /**
+   * Compute the normal (perpendicular) distance to a vector described by a
+   * vector taken from the origin.
+   * Monotonically increasing for arc distances up to PI/2.
+   *
+   * @param x is the x part of the vector to compute a distance to.
+   * @param y is the y part of the vector to compute a distance to.
+   * @param z is the z part of the vector to compute a distance to.
+   * @return the normal distance.
+   */
+  public double normalDistance(final double x, final double y, final double z) {
+    return Math.sqrt(normalDistanceSquared(x, y, z));
+  }
+
+  /**
+   * Compute the magnitude of this vector.
+   *
+   * @return the magnitude.
+   */
+  public double magnitude() {
+    return magnitude(x,y,z);
+  }
+
+  /** Compute the desired magnitude of a unit vector projected to a given
+   * planet model.
+   * @param planetModel is the planet model.
+   * @param x is the unit vector x value.
+   * @param y is the unit vector y value.
+   * @param z is the unit vector z value.
+   * @return a magnitude value for that (x,y,z) that projects the vector onto the specified ellipsoid.
+   */
+  protected static double computeDesiredEllipsoidMagnitude(final PlanetModel planetModel, final double x, final double y, final double z) {
+    return 1.0 / Math.sqrt(x*x*planetModel.inverseAbSquared + y*y*planetModel.inverseAbSquared + z*z*planetModel.inverseCSquared);
+  }
+
+  /** Compute the desired magnitude of a unit vector projected to a given
+   * planet model.  The unit vector is specified only by a z value.
+   * @param planetModel is the planet model.
+   * @param z is the unit vector z value.
+   * @return a magnitude value for that z value that projects the vector onto the specified ellipsoid.
+   */
+  protected static double computeDesiredEllipsoidMagnitude(final PlanetModel planetModel, final double z) {
+    return 1.0 / Math.sqrt((1.0-z*z)*planetModel.inverseAbSquared + z*z*planetModel.inverseCSquared);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof Vector))
+      return false;
+    Vector other = (Vector) o;
+    return (other.x == x && other.y == y && other.z == z);
+  }
+
+  @Override
+  public int hashCode() {
+    int result;
+    long temp;
+    temp = Double.doubleToLongBits(x);
+    result = (int) (temp ^ (temp >>> 32));
+    temp = Double.doubleToLongBits(y);
+    result = 31 * result + (int) (temp ^ (temp >>> 32));
+    temp = Double.doubleToLongBits(z);
+    result = 31 * result + (int) (temp ^ (temp >>> 32));
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "[X=" + x + ", Y=" + y + ", Z=" + z + "]";
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYZBounds.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYZBounds.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYZBounds.java
new file mode 100644
index 0000000..c3ee53d
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYZBounds.java
@@ -0,0 +1,267 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * An object for accumulating XYZ bounds information.
+ *
+ * @lucene.experimental
+ */
+public class XYZBounds implements Bounds {
+
+  /** A 'fudge factor', which is added to maximums and subtracted from minimums,
+   * in order to compensate for potential error deltas.  This would not be necessary
+   * except that our 'bounds' is defined as always equaling or exceeding the boundary
+   * of the shape, and we cannot guarantee that without making MINIMUM_RESOLUTION
+   * unacceptably large.
+   */
+  protected static final double FUDGE_FACTOR = Vector.MINIMUM_RESOLUTION * 2.0;
+  
+  /** Minimum x */
+  protected Double minX = null;
+  /** Maximum x */
+  protected Double maxX = null;
+  /** Minimum y */
+  protected Double minY = null;
+  /** Maximum y */
+  protected Double maxY = null;
+  /** Minimum z */
+  protected Double minZ = null;
+  /** Maximum z */
+  protected Double maxZ = null;
+  
+  /** 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;
+
+  /** Construct an empty bounds object */
+  public XYZBounds() {
+  }
+
+  // Accessor methods
+  
+  /** Return the minimum X value.
+   *@return minimum X value.
+   */
+  public Double getMinimumX() {
+    return minX;
+  }
+
+  /** Return the maximum X value.
+   *@return maximum X value.
+   */
+  public Double getMaximumX() {
+    return maxX;
+  }
+
+  /** Return the minimum Y value.
+   *@return minimum Y value.
+   */
+  public Double getMinimumY() {
+    return minY;
+  }
+
+  /** Return the maximum Y value.
+   *@return maximum Y value.
+   */
+  public Double getMaximumY() {
+    return maxY;
+  }
+  
+  /** Return the minimum Z value.
+   *@return minimum Z value.
+   */
+  public Double getMinimumZ() {
+    return minZ;
+  }
+
+  /** Return the maximum Z value.
+   *@return maximum Z value.
+   */
+  public Double getMaximumZ() {
+    return maxZ;
+  }
+
+  /** Return true if minX is as small as the planet model allows.
+   *@return true if minX has reached its bound.
+   */
+  public boolean isSmallestMinX(final PlanetModel planetModel) {
+    if (minX == null)
+      return false;
+    return minX - planetModel.getMinimumXValue() < Vector.MINIMUM_RESOLUTION;
+  }
+  
+  /** Return true if maxX is as large as the planet model allows.
+   *@return true if maxX has reached its bound.
+   */
+  public boolean isLargestMaxX(final PlanetModel planetModel) {
+    if (maxX == null)
+      return false;
+    return planetModel.getMaximumXValue() - maxX < Vector.MINIMUM_RESOLUTION;
+  }
+
+  /** Return true if minY is as small as the planet model allows.
+   *@return true if minY has reached its bound.
+   */
+  public boolean isSmallestMinY(final PlanetModel planetModel) {
+    if (minY == null)
+      return false;
+    return minY - planetModel.getMinimumYValue() < Vector.MINIMUM_RESOLUTION;
+  }
+  
+  /** Return true if maxY is as large as the planet model allows.
+   *@return true if maxY has reached its bound.
+   */
+  public boolean isLargestMaxY(final PlanetModel planetModel) {
+    if (maxY == null)
+      return false;
+    return planetModel.getMaximumYValue() - maxY < Vector.MINIMUM_RESOLUTION;
+  }
+  
+  /** Return true if minZ is as small as the planet model allows.
+   *@return true if minZ has reached its bound.
+   */
+  public boolean isSmallestMinZ(final PlanetModel planetModel) {
+    if (minZ == null)
+      return false;
+    return minZ - planetModel.getMinimumZValue() < Vector.MINIMUM_RESOLUTION;
+  }
+  
+  /** Return true if maxZ is as large as the planet model allows.
+   *@return true if maxZ has reached its bound.
+   */
+  public boolean isLargestMaxZ(final PlanetModel planetModel) {
+    if (maxZ == null)
+      return false;
+    return planetModel.getMaximumZValue() - maxZ < Vector.MINIMUM_RESOLUTION;
+  }
+
+  // Modification methods
+  
+  @Override
+  public Bounds addPlane(final PlanetModel planetModel, final Plane plane, final Membership... bounds) {
+    plane.recordBounds(planetModel, this, bounds);
+    return this;
+  }
+
+  /** 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.
+   *@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) {
+    return addPlane(planetModel, horizontalPlane, 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) {
+    return addPlane(planetModel, verticalPlane, bounds);
+  }
+
+  @Override
+  public Bounds addXValue(final GeoPoint point) {
+    final double x = point.x;
+    final double small = x - FUDGE_FACTOR;
+    if (minX == null || minX > small) {
+      minX = new Double(small);
+    }
+    final double large = x + FUDGE_FACTOR;
+    if (maxX == null || maxX < large) {
+      maxX = new Double(large);
+    }
+    return this;
+  }
+
+  @Override
+  public Bounds addYValue(final GeoPoint point) {
+    final double y = point.y;
+    final double small = y - FUDGE_FACTOR;
+    if (minY == null || minY > small) {
+      minY = new Double(small);
+    }
+    final double large = y + FUDGE_FACTOR;
+    if (maxY == null || maxY < large) {
+      maxY = new Double(large);
+    }
+    return this;
+  }
+
+  @Override
+  public Bounds addZValue(final GeoPoint point) {
+    final double z = point.z;
+    final double small = z - FUDGE_FACTOR;
+    if (minZ == null || minZ > small) {
+      minZ = new Double(small);
+    }
+    final double large = z + FUDGE_FACTOR;
+    if (maxZ == null || maxZ < large) {
+      maxZ = new Double(large);
+    }
+    return this;
+  }
+
+  @Override
+  public Bounds addPoint(final GeoPoint point) {
+    return addXValue(point).addYValue(point).addZValue(point);
+  }
+
+  @Override
+  public Bounds isWide() {
+    // No specific thing we need to do.
+    return this;
+  }
+
+  @Override
+  public Bounds noLongitudeBound() {
+    // No specific thing we need to do.
+    return this;
+  }
+
+  @Override
+  public Bounds noTopLatitudeBound() {
+    // No specific thing we need to do.
+    return this;
+  }
+
+  @Override
+  public Bounds noBottomLatitudeBound() {
+    // No specific thing we need to do.
+    return this;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYZSolid.java
new file mode 100644
index 0000000..9298079
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYZSolid.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Interface for a family of 3D rectangles, bounded on six sides by X,Y,Z limits
+ *
+ * @lucene.internal
+ */
+public interface XYZSolid extends GeoArea {
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYZSolidFactory.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYZSolidFactory.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYZSolidFactory.java
new file mode 100644
index 0000000..25ea400
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYZSolidFactory.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Factory for {@link XYZSolid}.
+ *
+ * @lucene.experimental
+ */
+public class XYZSolidFactory {
+  private XYZSolidFactory() {
+  }
+
+  /**
+   * Create a XYZSolid of the right kind given (x,y,z) bounds.
+   * @param planetModel is the planet model
+   * @param minX is the min X boundary
+   * @param maxX is the max X boundary
+   * @param minY is the min Y boundary
+   * @param maxY is the max Y boundary
+   * @param minZ is the min Z boundary
+   * @param maxZ is the max Z boundary
+   */
+  public static XYZSolid makeXYZSolid(final PlanetModel planetModel, final double minX, final double maxX, final double minY, final double maxY, final double minZ, final double maxZ) {
+    if (Math.abs(maxX - minX) < Vector.MINIMUM_RESOLUTION) {
+      if (Math.abs(maxY - minY) < Vector.MINIMUM_RESOLUTION) {
+        if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
+          return new dXdYdZSolid(planetModel, (minX+maxX) * 0.5, (minY+maxY) * 0.5, minZ);
+        } else {
+          return new dXdYZSolid(planetModel, (minX+maxX) * 0.5, (minY+maxY) * 0.5, minZ, maxZ);
+        }
+      } else {
+        if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
+          return new dXYdZSolid(planetModel, (minX+maxX) * 0.5, minY, maxY, (minZ+maxZ) * 0.5);
+        } else {
+          return new dXYZSolid(planetModel, (minX+maxX) * 0.5, minY, maxY, minZ, maxZ);
+        }
+      }
+    }
+    if (Math.abs(maxY - minY) < Vector.MINIMUM_RESOLUTION) {
+      if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
+        return new XdYdZSolid(planetModel, minX, maxX, (minY+maxY) * 0.5, (minZ+maxZ) * 0.5);
+      } else {
+        return new XdYZSolid(planetModel, minX, maxX, (minY+maxY) * 0.5, minZ, maxZ);
+      }
+    }
+    if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
+      return new XYdZSolid(planetModel, minX, maxX, minY, maxY, (minZ+maxZ) * 0.5);
+    }
+    return new StandardXYZSolid(planetModel, minX, maxX, minY, maxY, minZ, maxZ);
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYdZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYdZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYdZSolid.java
new file mode 100644
index 0000000..66aac84
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XYdZSolid.java
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in Z
+ *
+ * @lucene.internal
+ */
+public class XYdZSolid extends BaseXYZSolid {
+
+  /** Min-X plane */
+  protected final SidedPlane minXPlane;
+  /** Max-X plane */
+  protected final SidedPlane maxXPlane;
+  /** Min-Y plane */
+  protected final SidedPlane minYPlane;
+  /** Max-Y plane */
+  protected final SidedPlane maxYPlane;
+  /** Z plane */
+  protected final Plane zPlane;
+  
+  /** These are the edge points of the shape, which are defined to be at least one point on
+   * each surface area boundary.  In the case of a solid, this includes points which represent
+   * the intersection of XYZ bounding planes and the planet, as well as points representing
+   * the intersection of single bounding planes with the planet itself.
+   */
+  protected final GeoPoint[] edgePoints;
+
+  /** Notable points for ZPlane */
+  protected final GeoPoint[] notableZPoints;
+
+  /**
+   * Sole constructor
+   *
+   *@param planetModel is the planet model.
+   *@param minX is the minimum X value.
+   *@param maxX is the maximum X value.
+   *@param minY is the minimum Y value.
+   *@param maxY is the maximum Y value.
+   *@param Z is the Z value.
+   */
+  public XYdZSolid(final PlanetModel planetModel,
+    final double minX,
+    final double maxX,
+    final double minY,
+    final double maxY,
+    final double Z) {
+    super(planetModel);
+    // Argument checking
+    if (maxX - minX < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("X values in wrong order or identical");
+    if (maxY - minY < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("Y values in wrong order or identical");
+
+    final double worldMinZ = planetModel.getMinimumZValue();
+    final double worldMaxZ = planetModel.getMaximumZValue();
+    
+    // Construct the planes
+    minXPlane = new SidedPlane(maxX,0.0,0.0,xUnitVector,-minX);
+    maxXPlane = new SidedPlane(minX,0.0,0.0,xUnitVector,-maxX);
+    minYPlane = new SidedPlane(0.0,maxY,0.0,yUnitVector,-minY);
+    maxYPlane = new SidedPlane(0.0,minY,0.0,yUnitVector,-maxY);
+    zPlane = new Plane(zUnitVector,-Z);
+      
+    // We need at least one point on the planet surface for each manifestation of the shape.
+    // There can be up to 2 (on opposite sides of the world).  But we have to go through
+    // 4 combinations of adjacent planes in order to find out if any have 2 intersection solution.
+    // Typically, this requires 4 square root operations. 
+    final GeoPoint[] minXZ = minXPlane.findIntersections(planetModel,zPlane,maxXPlane,minYPlane,maxYPlane);
+    final GeoPoint[] maxXZ = maxXPlane.findIntersections(planetModel,zPlane,minXPlane,minYPlane,maxYPlane);
+    final GeoPoint[] minYZ = minYPlane.findIntersections(planetModel,zPlane,maxYPlane,minXPlane,maxXPlane);
+    final GeoPoint[] maxYZ = maxYPlane.findIntersections(planetModel,zPlane,minYPlane,minXPlane,maxXPlane);
+      
+    notableZPoints = glueTogether(minXZ, maxXZ, minYZ, maxYZ);
+
+    // Now, compute the edge points.
+    // This is the trickiest part of setting up an XYZSolid.  We've computed intersections already, so
+    // we'll start there.  We know that at most there will be two disconnected shapes on the planet surface.
+    // But there's also a case where exactly one plane slices through the world, and none of the bounding plane
+    // intersections do.  Thus, if we don't find any of the edge intersection cases, we have to look for that last case.
+      
+    // If we still haven't encountered anything, we need to look at single-plane/world intersections.
+    // We detect these by looking at the world model and noting its x, y, and z bounds.
+    // The cases we are looking for are when the four corner points for any given
+    // plane are all outside of the world, AND that plane intersects the world.
+    // There are four corner points all told; we must evaluate these WRT the planet surface.
+    final boolean minXminYZ = planetModel.pointOutside(minX, minY, Z);
+    final boolean minXmaxYZ = planetModel.pointOutside(minX, maxY, Z);
+    final boolean maxXminYZ = planetModel.pointOutside(maxX, minY, Z);
+    final boolean maxXmaxYZ = planetModel.pointOutside(maxX, maxY, Z);
+
+    final GeoPoint[] zEdges;
+    if (Z - worldMinZ >= -Vector.MINIMUM_RESOLUTION && Z - worldMaxZ <= Vector.MINIMUM_RESOLUTION &&
+      minX < 0.0 && maxX > 0.0 && minY < 0.0 && maxY > 0.0 &&
+      minXminYZ && minXmaxYZ && maxXminYZ && maxXmaxYZ) {
+      // Find any point on the minZ plane that intersects the world
+      // First construct a perpendicular plane that will allow us to find a sample point.
+      // This plane is vertical and goes through the points (0,0,0) and (1,0,0)
+      // Then use it to compute a sample point.
+      final GeoPoint intPoint = zPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
+      if (intPoint != null) {
+        zEdges = new GeoPoint[]{intPoint};
+      } else {
+        zEdges = EMPTY_POINTS;
+      }
+    } else {
+      zEdges= EMPTY_POINTS;
+    }
+
+    this.edgePoints = glueTogether(minXZ, maxXZ, minYZ, maxYZ, zEdges);
+  }
+
+  @Override
+  protected GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+  
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return minXPlane.isWithin(x, y, z) &&
+      maxXPlane.isWithin(x, y, z) &&
+      minYPlane.isWithin(x, y, z) &&
+      maxYPlane.isWithin(x, y, z) &&
+      zPlane.evaluateIsZero(x, y, z);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    
+    //System.err.println(this+" getrelationship with "+path);
+    final int insideRectangle = isShapeInsideArea(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some inside");
+      return OVERLAPS;
+    }
+
+    // Figure out if the entire XYZArea is contained by the shape.
+    final int insideShape = isAreaInsideShape(path);
+    if (insideShape == SOME_INSIDE) {
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
+      //System.err.println(" inside of each other");
+      return OVERLAPS;
+    }
+
+    if (path.intersects(zPlane, notableZPoints, minXPlane, maxXPlane, minYPlane, maxYPlane)) {
+      //System.err.println(" edges intersect");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      //System.err.println(" shape inside rectangle");
+      return WITHIN;
+    }
+
+    if (insideShape == ALL_INSIDE) {
+      //System.err.println(" shape contains rectangle");
+      return CONTAINS;
+    }
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof XYdZSolid))
+      return false;
+    XYdZSolid other = (XYdZSolid) o;
+    if (!super.equals(other)) {
+      return false;
+    }
+    return other.minXPlane.equals(minXPlane) &&
+      other.maxXPlane.equals(maxXPlane) &&
+      other.minYPlane.equals(minYPlane) &&
+      other.maxYPlane.equals(maxYPlane) &&
+      other.zPlane.equals(zPlane);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result  + minXPlane.hashCode();
+    result = 31 * result  + maxXPlane.hashCode();
+    result = 31 * result  + minYPlane.hashCode();
+    result = 31 * result  + maxYPlane.hashCode();
+    result = 31 * result  + zPlane.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "XYdZSolid: {planetmodel="+planetModel+", minXplane="+minXPlane+", maxXplane="+maxXPlane+", minYplane="+minYPlane+", maxYplane="+maxYPlane+", zplane="+zPlane+"}";
+  }
+  
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XdYZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XdYZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XdYZSolid.java
new file mode 100644
index 0000000..d9e11b8
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XdYZSolid.java
@@ -0,0 +1,212 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in Y
+ *
+ * @lucene.internal
+ */
+public class XdYZSolid extends BaseXYZSolid {
+
+  /** Min-X plane */
+  protected final SidedPlane minXPlane;
+  /** Max-X plane */
+  protected final SidedPlane maxXPlane;
+  /** Y plane */
+  protected final Plane yPlane;
+  /** Min-Z plane */
+  protected final SidedPlane minZPlane;
+  /** Max-Z plane */
+  protected final SidedPlane maxZPlane;
+  
+  /** These are the edge points of the shape, which are defined to be at least one point on
+   * each surface area boundary.  In the case of a solid, this includes points which represent
+   * the intersection of XYZ bounding planes and the planet, as well as points representing
+   * the intersection of single bounding planes with the planet itself.
+   */
+  protected final GeoPoint[] edgePoints;
+
+  /** Notable points for YPlane */
+  protected final GeoPoint[] notableYPoints;
+
+  /**
+   * Sole constructor
+   *
+   *@param planetModel is the planet model.
+   *@param minX is the minimum X value.
+   *@param maxX is the maximum X value.
+   *@param Y is the Y value.
+   *@param minZ is the minimum Z value.
+   *@param maxZ is the maximum Z value.
+   */
+  public XdYZSolid(final PlanetModel planetModel,
+    final double minX,
+    final double maxX,
+    final double Y,
+    final double minZ,
+    final double maxZ) {
+    super(planetModel);
+    // Argument checking
+    if (maxX - minX < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("X values in wrong order or identical");
+    if (maxZ - minZ < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("Z values in wrong order or identical");
+
+    final double worldMinY = planetModel.getMinimumYValue();
+    final double worldMaxY = planetModel.getMaximumYValue();
+    
+    // Construct the planes
+    minXPlane = new SidedPlane(maxX,0.0,0.0,xUnitVector,-minX);
+    maxXPlane = new SidedPlane(minX,0.0,0.0,xUnitVector,-maxX);
+    yPlane = new Plane(yUnitVector,-Y);
+    minZPlane = new SidedPlane(0.0,0.0,maxZ,zUnitVector,-minZ);
+    maxZPlane = new SidedPlane(0.0,0.0,minZ,zUnitVector,-maxZ);
+      
+    // We need at least one point on the planet surface for each manifestation of the shape.
+    // There can be up to 2 (on opposite sides of the world).  But we have to go through
+    // 4 combinations of adjacent planes in order to find out if any have 2 intersection solution.
+    // Typically, this requires 4 square root operations. 
+    final GeoPoint[] minXY = minXPlane.findIntersections(planetModel,yPlane,maxXPlane,minZPlane,maxZPlane);
+    final GeoPoint[] maxXY = maxXPlane.findIntersections(planetModel,yPlane,minXPlane,minZPlane,maxZPlane);
+    final GeoPoint[] YminZ = yPlane.findIntersections(planetModel,minZPlane,maxZPlane,minXPlane,maxXPlane);
+    final GeoPoint[] YmaxZ = yPlane.findIntersections(planetModel,maxZPlane,minZPlane,minXPlane,maxXPlane);
+      
+    notableYPoints = glueTogether(minXY, maxXY, YminZ, YmaxZ);
+
+    // Now, compute the edge points.
+    // This is the trickiest part of setting up an XYZSolid.  We've computed intersections already, so
+    // we'll start there.  We know that at most there will be two disconnected shapes on the planet surface.
+    // But there's also a case where exactly one plane slices through the world, and none of the bounding plane
+    // intersections do.  Thus, if we don't find any of the edge intersection cases, we have to look for that last case.
+      
+    // We need to look at single-plane/world intersections.
+    // We detect these by looking at the world model and noting its x, y, and z bounds.
+    // The cases we are looking for are when the four corner points for any given
+    // plane are all outside of the world, AND that plane intersects the world.
+    // There are four corner points all told; we must evaluate these WRT the planet surface.
+    final boolean minXYminZ = planetModel.pointOutside(minX, Y, minZ);
+    final boolean minXYmaxZ = planetModel.pointOutside(minX, Y, maxZ);
+    final boolean maxXYminZ = planetModel.pointOutside(maxX, Y, minZ);
+    final boolean maxXYmaxZ = planetModel.pointOutside(maxX, Y, maxZ);
+
+    final GeoPoint[] yEdges;
+    if (Y - worldMinY >= -Vector.MINIMUM_RESOLUTION && Y - worldMaxY <= Vector.MINIMUM_RESOLUTION &&
+      minX < 0.0 && maxX > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
+      minXYminZ && minXYmaxZ && maxXYminZ && maxXYmaxZ) {
+      // Find any point on the minY plane that intersects the world
+      // First construct a perpendicular plane that will allow us to find a sample point.
+      // This plane is vertical and goes through the points (0,0,0) and (0,1,0)
+      // Then use it to compute a sample point.
+      final GeoPoint intPoint = yPlane.getSampleIntersectionPoint(planetModel, yVerticalPlane);
+      if (intPoint != null) {
+        yEdges = new GeoPoint[]{intPoint};
+      } else {
+        yEdges = EMPTY_POINTS;
+      }
+    } else {
+      yEdges = EMPTY_POINTS;
+    }
+
+    this.edgePoints = glueTogether(minXY, maxXY, YminZ, YmaxZ, yEdges);
+  }
+
+  @Override
+  protected GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+  
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return minXPlane.isWithin(x, y, z) &&
+      maxXPlane.isWithin(x, y, z) &&
+      yPlane.evaluateIsZero(x, y, z) &&
+      minZPlane.isWithin(x, y, z) &&
+      maxZPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    //System.err.println(this+" getrelationship with "+path);
+    final int insideRectangle = isShapeInsideArea(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some inside");
+      return OVERLAPS;
+    }
+
+    // Figure out if the entire XYZArea is contained by the shape.
+    final int insideShape = isAreaInsideShape(path);
+    if (insideShape == SOME_INSIDE) {
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
+      //System.err.println(" inside of each other");
+      return OVERLAPS;
+    }
+
+    if (path.intersects(yPlane, notableYPoints, minXPlane, maxXPlane, minZPlane, maxZPlane)) {
+      //System.err.println(" edges intersect");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      //System.err.println(" shape inside rectangle");
+      return WITHIN;
+    }
+
+    if (insideShape == ALL_INSIDE) {
+      //System.err.println(" shape contains rectangle");
+      return CONTAINS;
+    }
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof XdYZSolid))
+      return false;
+    XdYZSolid other = (XdYZSolid) o;
+    if (!super.equals(other)) {
+      return false;
+    }
+    return other.minXPlane.equals(minXPlane) &&
+      other.maxXPlane.equals(maxXPlane) &&
+      other.yPlane.equals(yPlane) &&
+      other.minZPlane.equals(minZPlane) &&
+      other.maxZPlane.equals(maxZPlane);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result  + minXPlane.hashCode();
+    result = 31 * result  + maxXPlane.hashCode();
+    result = 31 * result  + yPlane.hashCode();
+    result = 31 * result  + minZPlane.hashCode();
+    result = 31 * result  + maxZPlane.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "XdYZSolid: {planetmodel="+planetModel+", minXplane="+minXPlane+", maxXplane="+maxXPlane+", yplane="+yPlane+", minZplane="+minZPlane+", maxZplane="+maxZPlane+"}";
+  }
+  
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XdYdZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XdYdZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XdYdZSolid.java
new file mode 100644
index 0000000..33d0bea
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/XdYdZSolid.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in Y and Z.
+ * This figure, in fact, represents either zero, one, or two points, so the
+ * actual data stored is minimal.
+ *
+ * @lucene.internal
+ */
+public class XdYdZSolid extends BaseXYZSolid {
+
+  /** The points in this figure on the planet surface; also doubles for edge points */
+  protected final GeoPoint[] surfacePoints;
+  
+  /**
+   * Sole constructor
+   *
+   *@param planetModel is the planet model.
+   *@param minX is the minimum X value.
+   *@param maxX is the maximum X value.
+   *@param Y is the Y value.
+   *@param Z is the Z value.
+   */
+  public XdYdZSolid(final PlanetModel planetModel,
+    final double minX,
+    final double maxX,
+    final double Y,
+    final double Z) {
+    super(planetModel);
+    // Argument checking
+    if (maxX - minX < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("X values in wrong order or identical");
+
+    // Build the planes and intersect them.
+    final Plane yPlane = new Plane(yUnitVector,-Y);
+    final Plane zPlane = new Plane(zUnitVector,-Z);
+    final SidedPlane minXPlane = new SidedPlane(maxX,0.0,0.0,xUnitVector,-minX);
+    final SidedPlane maxXPlane = new SidedPlane(minX,0.0,0.0,xUnitVector,-maxX);
+    surfacePoints = yPlane.findIntersections(planetModel,zPlane,minXPlane,maxXPlane);
+  }
+
+  @Override
+  protected GeoPoint[] getEdgePoints() {
+    return surfacePoints;
+  }
+  
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    for (final GeoPoint p : surfacePoints) {
+      if (p.isIdentical(x,y,z))
+        return true;
+    }
+    return false;
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    //System.err.println(this+" getrelationship with "+path);
+    final int insideRectangle = isShapeInsideArea(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some inside");
+      return OVERLAPS;
+    }
+
+    // Figure out if the entire XYZArea is contained by the shape.
+    final int insideShape = isAreaInsideShape(path);
+    if (insideShape == SOME_INSIDE) {
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
+      //System.err.println(" inside of each other");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      return WITHIN;
+    }
+    
+    if (insideShape == ALL_INSIDE) {
+      //System.err.println(" shape contains rectangle");
+      return CONTAINS;
+    }
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof XdYdZSolid))
+      return false;
+    XdYdZSolid other = (XdYdZSolid) o;
+    if (!super.equals(other) || surfacePoints.length != other.surfacePoints.length ) {
+      return false;
+    }
+    for (int i = 0; i < surfacePoints.length; i++) {
+      if (!surfacePoints[i].equals(other.surfacePoints[i]))
+        return false;
+    }
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    for (final GeoPoint p : surfacePoints) {
+      result = 31 * result  + p.hashCode();
+    }
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    final StringBuilder sb = new StringBuilder();
+    for (final GeoPoint p : surfacePoints) {
+      sb.append(" ").append(p).append(" ");
+    }
+    return "XdYdZSolid: {planetmodel="+planetModel+", "+sb.toString()+"}";
+  }
+  
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXYZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXYZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXYZSolid.java
new file mode 100644
index 0000000..48fe714
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/dXYZSolid.java
@@ -0,0 +1,216 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in X.
+ *
+ * @lucene.internal
+ */
+public class dXYZSolid extends BaseXYZSolid {
+
+  /** X plane */
+  protected final Plane xPlane;
+  /** Min-Y plane */
+  protected final SidedPlane minYPlane;
+  /** Max-Y plane */
+  protected final SidedPlane maxYPlane;
+  /** Min-Z plane */
+  protected final SidedPlane minZPlane;
+  /** Max-Z plane */
+  protected final SidedPlane maxZPlane;
+  
+  /** These are the edge points of the shape, which are defined to be at least one point on
+   * each surface area boundary.  In the case of a solid, this includes points which represent
+   * the intersection of XYZ bounding planes and the planet, as well as points representing
+   * the intersection of single bounding planes with the planet itself.
+   */
+  protected final GeoPoint[] edgePoints;
+
+  /** Notable points for XPlane */
+  protected final GeoPoint[] notableXPoints;
+
+  /**
+   * Sole constructor
+   *
+   *@param planetModel is the planet model.
+   *@param X is the X value.
+   *@param minY is the minimum Y value.
+   *@param maxY is the maximum Y value.
+   *@param minZ is the minimum Z value.
+   *@param maxZ is the maximum Z value.
+   */
+  public dXYZSolid(final PlanetModel planetModel,
+    final double X,
+    final double minY,
+    final double maxY,
+    final double minZ,
+    final double maxZ) {
+    super(planetModel);
+    // Argument checking
+    if (maxY - minY < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("Y values in wrong order or identical");
+    if (maxZ - minZ < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("Z values in wrong order or identical");
+
+    final double worldMinX = planetModel.getMinimumXValue();
+    final double worldMaxX = planetModel.getMaximumXValue();
+    
+    // Construct the planes
+    xPlane = new Plane(xUnitVector,-X);
+    minYPlane = new SidedPlane(0.0,maxY,0.0,yUnitVector,-minY);
+    maxYPlane = new SidedPlane(0.0,minY,0.0,yUnitVector,-maxY);
+    minZPlane = new SidedPlane(0.0,0.0,maxZ,zUnitVector,-minZ);
+    maxZPlane = new SidedPlane(0.0,0.0,minZ,zUnitVector,-maxZ);
+      
+    // We need at least one point on the planet surface for each manifestation of the shape.
+    // There can be up to 2 (on opposite sides of the world).  But we have to go through
+    // 4 combinations of adjacent planes in order to find out if any have 2 intersection solution.
+    // Typically, this requires 4 square root operations. 
+    final GeoPoint[] XminY = xPlane.findIntersections(planetModel,minYPlane,maxYPlane,minZPlane,maxZPlane);
+    final GeoPoint[] XmaxY = xPlane.findIntersections(planetModel,maxYPlane,minYPlane,minZPlane,maxZPlane);
+    final GeoPoint[] XminZ = xPlane.findIntersections(planetModel,minZPlane,maxZPlane,minYPlane,maxYPlane);
+    final GeoPoint[] XmaxZ = xPlane.findIntersections(planetModel,maxZPlane,minZPlane,minYPlane,maxYPlane);
+
+    notableXPoints = glueTogether(XminY, XmaxY, XminZ, XmaxZ);
+
+    // Now, compute the edge points.
+    // This is the trickiest part of setting up an XYZSolid.  We've computed intersections already, so
+    // we'll start there.  We know that at most there will be two disconnected shapes on the planet surface.
+    // But there's also a case where exactly one plane slices through the world, and none of the bounding plane
+    // intersections do.  Thus, if we don't find any of the edge intersection cases, we have to look for that last case.
+      
+    // We need to look at single-plane/world intersections.
+    // We detect these by looking at the world model and noting its x, y, and z bounds.
+    // For the single-dimension degenerate case, there's really only one plane that can possibly intersect the world.
+    // The cases we are looking for are when the four corner points for any given
+    // plane are all outside of the world, AND that plane intersects the world.
+    // There are four corner points all told; we must evaluate these WRT the planet surface.
+    final boolean XminYminZ = planetModel.pointOutside(X, minY, minZ);
+    final boolean XminYmaxZ = planetModel.pointOutside(X, minY, maxZ);
+    final boolean XmaxYminZ = planetModel.pointOutside(X, maxY, minZ);
+    final boolean XmaxYmaxZ = planetModel.pointOutside(X, maxY, maxZ);
+
+    final GeoPoint[] xEdges;
+    if (X - worldMinX >= -Vector.MINIMUM_RESOLUTION && X - worldMaxX <= Vector.MINIMUM_RESOLUTION &&
+      minY < 0.0 && maxY > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
+      XminYminZ && XminYmaxZ && XmaxYminZ && XmaxYmaxZ) {
+      // Find any point on the X plane that intersects the world
+      // First construct a perpendicular plane that will allow us to find a sample point.
+      // This plane is vertical and goes through the points (0,0,0) and (1,0,0)
+      // Then use it to compute a sample point.
+      final GeoPoint intPoint = xPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
+      if (intPoint != null) {
+        xEdges = new GeoPoint[]{intPoint};
+      } else {
+        xEdges = EMPTY_POINTS;
+      }
+    } else {
+      xEdges = EMPTY_POINTS;
+    }
+
+    this.edgePoints = glueTogether(XminY,XmaxY,XminZ,XmaxZ,xEdges);
+  }
+
+  @Override
+  protected GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+  
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return xPlane.evaluateIsZero(x, y, z) &&
+      minYPlane.isWithin(x, y, z) &&
+      maxYPlane.isWithin(x, y, z) &&
+      minZPlane.isWithin(x, y, z) &&
+      maxZPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    //System.err.println(this+" getrelationship with "+path);
+    final int insideRectangle = isShapeInsideArea(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some shape points inside area");
+      return OVERLAPS;
+    }
+
+    // Figure out if the entire XYZArea is contained by the shape.
+    final int insideShape = isAreaInsideShape(path);
+    if (insideShape == SOME_INSIDE) {
+      //System.err.println(" some area points inside shape");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
+      //System.err.println(" inside of each other");
+      return OVERLAPS;
+    }
+
+    // The entire locus of points in this shape is on a single plane, so we only need ot look for an intersection with that plane.
+    //System.err.println("xPlane = "+xPlane);
+    if (path.intersects(xPlane, notableXPoints, minYPlane, maxYPlane, minZPlane, maxZPlane)) {
+      //System.err.println(" edges intersect");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      //System.err.println(" shape points inside area");
+      return WITHIN;
+    }
+
+    if (insideShape == ALL_INSIDE) {
+      //System.err.println(" shape contains all area");
+      return CONTAINS;
+    }
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof dXYZSolid))
+      return false;
+    dXYZSolid other = (dXYZSolid) o;
+    if (!super.equals(other)) {
+      return false;
+    }
+    return other.xPlane.equals(xPlane) &&
+      other.minYPlane.equals(minYPlane) &&
+      other.maxYPlane.equals(maxYPlane) &&
+      other.minZPlane.equals(minZPlane) &&
+      other.maxZPlane.equals(maxZPlane);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result  + xPlane.hashCode();
+    result = 31 * result  + minYPlane.hashCode();
+    result = 31 * result  + maxYPlane.hashCode();
+    result = 31 * result  + minZPlane.hashCode();
+    result = 31 * result  + maxZPlane.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "dXYZSolid: {planetmodel="+planetModel+", xplane="+xPlane+", minYplane="+minYPlane+", maxYplane="+maxYPlane+", minZplane="+minZPlane+", maxZplane="+maxZPlane+"}";
+  }
+  
+}
+  


[22/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoConvexPolygon.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoConvexPolygon.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoConvexPolygon.java
deleted file mode 100755
index fc07c4b..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoConvexPolygon.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.List;
-
-/**
- * GeoConvexPolygon objects are generic building blocks of more complex structures.
- * The only restrictions on these objects are: (1) they must be convex; (2) they must have
- * a maximum extent no larger than PI.  Violating either one of these limits will
- * cause the logic to fail.
- *
- * @lucene.experimental
- */
-public class GeoConvexPolygon extends GeoBasePolygon {
-  /** The list of polygon points */
-  protected final List<GeoPoint> points;
-  /** A bitset describing, for each edge, whether it is internal or not */
-  protected final BitSet isInternalEdges;
-
-  /** A list of edges */
-  protected SidedPlane[] edges = null;
-  /** The set of notable points for each edge */
-  protected GeoPoint[][] notableEdgePoints = null;
-  /** A point which is on the boundary of the polygon */
-  protected GeoPoint[] edgePoints = null;
-  /** Tracking the maximum distance we go at any one time, so to be sure it's legal */
-  protected double fullDistance = 0.0;
-  /** Set to true when the polygon is complete */
-  protected boolean isDone = false;
-  
-  /**
-   * Create a convex polygon from a list of points.  The first point must be on the
-   * external edge.
-   *@param planetModel is the planet model.
-   *@param pointList is the list of points to create the polygon from.
-   */
-  public GeoConvexPolygon(final PlanetModel planetModel, final List<GeoPoint> pointList) {
-    super(planetModel);
-    this.points = pointList;
-    this.isInternalEdges = new BitSet();
-    done(false);
-  }
-
-  /**
-   * Create a convex polygon from a list of points, keeping track of which boundaries
-   * are internal.  This is used when creating a polygon as a building block for another shape.
-   *@param planetModel is the planet model.
-   *@param pointList is the set of points to create the polygon from.
-   *@param internalEdgeFlags is a bitset describing whether each edge is internal or not.
-   *@param returnEdgeInternal is true when the final return edge is an internal one.
-   */
-  public GeoConvexPolygon(final PlanetModel planetModel, final List<GeoPoint> pointList, final BitSet internalEdgeFlags,
-                          final boolean returnEdgeInternal) {
-    super(planetModel);
-    this.points = pointList;
-    this.isInternalEdges = internalEdgeFlags;
-    done(returnEdgeInternal);
-  }
-
-  /**
-   * Create a convex polygon, with a starting latitude and longitude.
-   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
-   *@param planetModel is the planet model.
-   *@param startLatitude is the latitude of the first point.
-   *@param startLongitude is the longitude of the first point.
-   */
-  public GeoConvexPolygon(final PlanetModel planetModel, final double startLatitude, final double startLongitude) {
-    super(planetModel);
-    points = new ArrayList<>();
-    isInternalEdges = new BitSet();
-    points.add(new GeoPoint(planetModel, startLatitude, startLongitude));
-  }
-
-  /**
-   * Add a point to the polygon.
-   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
-   *
-   * @param latitude       is the latitude of the next point.
-   * @param longitude      is the longitude of the next point.
-   * @param isInternalEdge is true if the edge just added with this point should be considered "internal", and not
-   *                       intersected as part of the intersects() operation.
-   */
-  public void addPoint(final double latitude, final double longitude, final boolean isInternalEdge) {
-    if (isDone)
-      throw new IllegalStateException("Can't call addPoint() if done() already called");
-    if (isInternalEdge)
-      isInternalEdges.set(points.size() - 1);
-    points.add(new GeoPoint(planetModel, latitude, longitude));
-  }
-
-  /**
-   * Finish the polygon, by connecting the last added point with the starting point.
-   *@param isInternalReturnEdge is true if the return edge (back to start) is an internal one.
-   */
-  public void done(final boolean isInternalReturnEdge) {
-    if (isDone)
-      throw new IllegalStateException("Can't call done() more than once");
-    // If fewer than 3 points, can't do it.
-    if (points.size() < 3)
-      throw new IllegalArgumentException("Polygon needs at least three points.");
-
-    if (isInternalReturnEdge)
-      isInternalEdges.set(points.size() - 1);
-
-    isDone = true;
-    
-    // Time to construct the planes.  If the polygon is truly convex, then any adjacent point
-    // to a segment can provide an interior measurement.
-    edges = new SidedPlane[points.size()];
-    notableEdgePoints = new GeoPoint[points.size()][];
-
-    for (int i = 0; i < points.size(); i++) {
-      final GeoPoint start = points.get(i);
-      final GeoPoint end = points.get(legalIndex(i + 1));
-      final double distance = start.arcDistance(end);
-      if (distance > fullDistance)
-        fullDistance = distance;
-      final GeoPoint check = points.get(legalIndex(i + 2));
-      final SidedPlane sp = new SidedPlane(check, start, end);
-      //System.out.println("Created edge "+sp+" using start="+start+" end="+end+" check="+check);
-      edges[i] = sp;
-      notableEdgePoints[i] = new GeoPoint[]{start, end};
-    }
-    createCenterPoint();
-  }
-
-  /** Compute a reasonable center point.
-   */
-  protected void createCenterPoint() {
-    // In order to naively confirm that the polygon is convex, I would need to
-    // check every edge, and verify that every point (other than the edge endpoints)
-    // is within the edge's sided plane.  This is an order n^2 operation.  That's still
-    // not wrong, though, because everything else about polygons has a similar cost.
-    for (int edgeIndex = 0; edgeIndex < edges.length; edgeIndex++) {
-      final SidedPlane edge = edges[edgeIndex];
-      for (int pointIndex = 0; pointIndex < points.size(); pointIndex++) {
-        if (pointIndex != edgeIndex && pointIndex != legalIndex(edgeIndex + 1)) {
-          if (!edge.isWithin(points.get(pointIndex)))
-            throw new IllegalArgumentException("Polygon is not convex: Point " + points.get(pointIndex) + " Edge " + edge);
-        }
-      }
-    }
-    edgePoints = new GeoPoint[]{points.get(0)};
-  }
-
-  /** Compute a legal point index from a possibly illegal one, that may have wrapped.
-   *@param index is the index.
-   *@return the normalized index.
-   */
-  protected int legalIndex(int index) {
-    while (index >= points.size())
-      index -= points.size();
-    return index;
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    for (final SidedPlane edge : edges) {
-      if (!edge.isWithin(x, y, z))
-        return false;
-    }
-    return true;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    //System.err.println("Checking for polygon intersection with plane "+p+"...");
-    for (int edgeIndex = 0; edgeIndex < edges.length; edgeIndex++) {
-      final SidedPlane edge = edges[edgeIndex];
-      final GeoPoint[] points = this.notableEdgePoints[edgeIndex];
-      if (!isInternalEdges.get(edgeIndex)) {
-        //System.err.println(" non-internal edge "+edge);
-        // Edges flagged as 'internal only' are excluded from the matching
-        // Construct boundaries
-        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];
-          }
-        }
-        if (edge.intersects(planetModel, p, notablePoints, points, bounds, membershipBounds)) {
-          //System.err.println(" intersects!");
-          return true;
-        }
-      }
-    }
-    //System.err.println(" no intersection");
-    return false;
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-
-    // Add all the points
-    for (final GeoPoint point : points) {
-      bounds.addPoint(point);
-    }
-
-    // Add planes with membership.
-    for (int edgeIndex = 0; edgeIndex < edges.length; edgeIndex++) {
-      final SidedPlane edge = edges[edgeIndex];
-      // Construct boundaries
-      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];
-        }
-      }
-      bounds.addPlane(planetModel, edge, membershipBounds);
-    }
-  }
-
-  @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;
-    GeoConvexPolygon other = (GeoConvexPolygon) o;
-    if (!super.equals(other))
-      return false;
-    if (!other.isInternalEdges.equals(isInternalEdges))
-      return false;
-    return (other.points.equals(points));
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + points.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoConvexPolygon: {planetmodel=" + planetModel + ", points=" + points + "}";
-  }
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateHorizontalLine.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateHorizontalLine.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateHorizontalLine.java
deleted file mode 100644
index 6644f0d..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateHorizontalLine.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Degenerate bounding box limited on two sides (left lon, right lon).
- * The left-right maximum extent for this shape is PI; for anything larger, use
- * GeoWideDegenerateHorizontalLine.
- *
- * @lucene.internal
- */
-public class GeoDegenerateHorizontalLine extends GeoBaseBBox {
-  /** Latitude of horizontal line */
-  protected final double latitude;
-  /** Left bounding longitude of line */
-  protected final double leftLon;
-  /** Right bounding longitude of line */
-  protected final double rightLon;
-
-  /** Left hand endpoint of line */
-  protected final GeoPoint LHC;
-  /** Right hand endpoint of line */
-  protected final GeoPoint RHC;
-
-  /** The plane describing the line */
-  protected final Plane plane;
-  /** The left side end plane */
-  protected final SidedPlane leftPlane;
-  /** The right side end plane */
-  protected final SidedPlane rightPlane;
-
-  /** Notable points for the line */
-  protected final GeoPoint[] planePoints;
-
-  /** Center of line */
-  protected final GeoPoint centerPoint;
-  /** A point that's on the line */
-  protected final GeoPoint[] edgePoints;
-
-  /**
-   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
-   *@param planetModel is the planet model.
-   *@param latitude is the latitude of the line.
-   *@param leftLon is the left end longitude.
-   *@param rightLon is the right end longitude.
-   */
-  public GeoDegenerateHorizontalLine(final PlanetModel planetModel, final double latitude, final double leftLon, double rightLon) {
-    super(planetModel);
-    // Argument checking
-    if (latitude > Math.PI * 0.5 || latitude < -Math.PI * 0.5)
-      throw new IllegalArgumentException("Latitude out of range");
-    if (leftLon < -Math.PI || leftLon > Math.PI)
-      throw new IllegalArgumentException("Left longitude out of range");
-    if (rightLon < -Math.PI || rightLon > Math.PI)
-      throw new IllegalArgumentException("Right longitude out of range");
-    double extent = rightLon - leftLon;
-    if (extent < 0.0) {
-      extent += 2.0 * Math.PI;
-    }
-    if (extent > Math.PI)
-      throw new IllegalArgumentException("Width of rectangle too great");
-
-    this.latitude = latitude;
-    this.leftLon = leftLon;
-    this.rightLon = rightLon;
-
-    final double sinLatitude = Math.sin(latitude);
-    final double cosLatitude = Math.cos(latitude);
-    final double sinLeftLon = Math.sin(leftLon);
-    final double cosLeftLon = Math.cos(leftLon);
-    final double sinRightLon = Math.sin(rightLon);
-    final double cosRightLon = Math.cos(rightLon);
-
-    // Now build the two points
-    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);
-
-    // Normalize
-    while (leftLon > rightLon) {
-      rightLon += Math.PI * 2.0;
-    }
-    final double middleLon = (leftLon + rightLon) * 0.5;
-    final double sinMiddleLon = Math.sin(middleLon);
-    final double cosMiddleLon = Math.cos(middleLon);
-
-    this.centerPoint = new GeoPoint(planetModel, sinLatitude, sinMiddleLon, cosLatitude, cosMiddleLon);
-    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
-    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
-
-    this.planePoints = new GeoPoint[]{LHC, RHC};
-
-    this.edgePoints = new GeoPoint[]{centerPoint};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    double newTopLat = latitude + angle;
-    double newBottomLat = latitude - angle;
-    // Figuring out when we escalate to a special case requires some prefiguring
-    double currentLonSpan = rightLon - leftLon;
-    if (currentLonSpan < 0.0)
-      currentLonSpan += Math.PI * 2.0;
-    double newLeftLon = leftLon - angle;
-    double newRightLon = rightLon + angle;
-    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
-      newLeftLon = -Math.PI;
-      newRightLon = Math.PI;
-    }
-    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return plane.evaluateIsZero(x, y, z) &&
-        leftPlane.isWithin(x, y, z) &&
-        rightPlane.isWithin(x, y, z);
-  }
-
-  @Override
-  public double getRadius() {
-    double topAngle = centerPoint.arcDistance(RHC);
-    double bottomAngle = centerPoint.arcDistance(LHC);
-    return Math.max(topAngle, bottomAngle);
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    return centerPoint;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    return p.intersects(planetModel, plane, notablePoints, planePoints, bounds, leftPlane, rightPlane);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    bounds.addHorizontalPlane(planetModel, latitude, plane, leftPlane, rightPlane)
-      .addPoint(LHC).addPoint(RHC);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    //System.err.println("getting relationship between "+this+" and "+path);
-    if (path.intersects(plane, planePoints, leftPlane, rightPlane)) {
-      //System.err.println(" overlaps");
-      return OVERLAPS;
-    }
-
-    if (path.isWithin(centerPoint)) {
-      //System.err.println(" contains");
-      return CONTAINS;
-    }
-
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @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;
-    GeoDegenerateHorizontalLine other = (GeoDegenerateHorizontalLine) o;
-    return super.equals(other) && other.LHC.equals(LHC) && other.RHC.equals(RHC);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + LHC.hashCode();
-    result = 31 * result + RHC.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoDegenerateHorizontalLine: {planetmodel="+planetModel+", latitude=" + latitude + "(" + latitude * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightLon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
-  }
-}
-  
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLatitudeZone.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLatitudeZone.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLatitudeZone.java
deleted file mode 100644
index 4890733..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLatitudeZone.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * This GeoBBox represents an area rectangle of one specific latitude with
- * no longitude bounds.
- *
- * @lucene.internal
- */
-public class GeoDegenerateLatitudeZone extends GeoBaseBBox {
-  /** The latitude */
-  protected final double latitude;
-  /** Sine of the latitude */
-  protected final double sinLatitude;
-  /** Plane describing the latitude zone */
-  protected final Plane plane;
-  /** A point on the world that's also on the zone */
-  protected final GeoPoint interiorPoint;
-  /** An array consisting of the interiorPoint */
-  protected final GeoPoint[] edgePoints;
-  /** No notable points */
-  protected final static GeoPoint[] planePoints = new GeoPoint[0];
-
-  /** Constructor.
-   *@param planetModel is the planet model to use.
-   *@param latitude is the latitude of the latitude zone.
-   */
-  public GeoDegenerateLatitudeZone(final PlanetModel planetModel, final double latitude) {
-    super(planetModel);
-    this.latitude = latitude;
-
-    this.sinLatitude = Math.sin(latitude);
-    double cosLatitude = Math.cos(latitude);
-    this.plane = new Plane(planetModel, sinLatitude);
-    // Compute an interior point.
-    interiorPoint = new GeoPoint(planetModel, sinLatitude, 0.0, cosLatitude, 1.0);
-    edgePoints = new GeoPoint[]{interiorPoint};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    double newTopLat = latitude + angle;
-    double newBottomLat = latitude - angle;
-    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, -Math.PI, Math.PI);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return Math.abs(z - this.sinLatitude) < 1e-10;
-  }
-
-  @Override
-  public double getRadius() {
-    return Math.PI;
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    // Totally arbitrary
-    return interiorPoint;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    return p.intersects(planetModel, plane, notablePoints, planePoints, bounds);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    bounds.noLongitudeBound()
-      .addHorizontalPlane(planetModel, latitude, plane);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    // 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.
-    //System.out.println("Got here! latitude="+latitude+" path="+path);
-
-    if (path.intersects(plane, planePoints)) {
-      return OVERLAPS;
-    }
-
-    if (path.isWithin(interiorPoint)) {
-      return CONTAINS;
-    }
-
-    return DISJOINT;
-  }
-
-  @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;
-    GeoDegenerateLatitudeZone other = (GeoDegenerateLatitudeZone) o;
-    return super.equals(other) && other.latitude == latitude;
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    long temp = Double.doubleToLongBits(latitude);
-    result = 31 * result + (int) (temp ^ (temp >>> 32));
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoDegenerateLatitudeZone: {planetmodel="+planetModel+", lat=" + latitude + "(" + latitude * 180.0 / Math.PI + ")}";
-  }
-}
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLongitudeSlice.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLongitudeSlice.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLongitudeSlice.java
deleted file mode 100644
index b5eb902..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLongitudeSlice.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Degenerate longitude slice.
- *
- * @lucene.internal
- */
-public class GeoDegenerateLongitudeSlice extends GeoBaseBBox {
-  /** The longitude of the slice */
-  protected final double longitude;
-
-  /** The bounding plane for the slice (through both poles, perpendicular to the slice) */
-  protected final SidedPlane boundingPlane;
-  /** The plane of the slice */
-  protected final Plane plane;
-  /** A point on the slice */
-  protected final GeoPoint interiorPoint;
-  /** An array consisting of the one point chosen on the slice */
-  protected final GeoPoint[] edgePoints;
-  /** Notable points for the slice (north and south poles) */
-  protected final GeoPoint[] planePoints;
-
-  /**
-   * Accepts only values in the following ranges: lon: {@code -PI -> PI}
-   */
-  public GeoDegenerateLongitudeSlice(final PlanetModel planetModel, final double longitude) {
-    super(planetModel);
-    // Argument checking
-    if (longitude < -Math.PI || longitude > Math.PI)
-      throw new IllegalArgumentException("Longitude out of range");
-    this.longitude = longitude;
-
-    final double sinLongitude = Math.sin(longitude);
-    final double cosLongitude = Math.cos(longitude);
-
-    this.plane = new Plane(cosLongitude, sinLongitude);
-    // We need a bounding plane too, which is perpendicular to the longitude plane and sided so that the point (0.0, longitude) is inside.
-    this.interiorPoint = new GeoPoint(planetModel, 0.0, sinLongitude, 1.0, cosLongitude);
-    this.boundingPlane = new SidedPlane(interiorPoint, -sinLongitude, cosLongitude);
-    this.edgePoints = new GeoPoint[]{interiorPoint};
-    this.planePoints = new GeoPoint[]{planetModel.NORTH_POLE, planetModel.SOUTH_POLE};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    // Figuring out when we escalate to a special case requires some prefiguring
-    double newLeftLon = longitude - angle;
-    double newRightLon = longitude + angle;
-    double currentLonSpan = 2.0 * angle;
-    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
-      newLeftLon = -Math.PI;
-      newRightLon = Math.PI;
-    }
-    return GeoBBoxFactory.makeGeoBBox(planetModel, Math.PI * 0.5, -Math.PI * 0.5, newLeftLon, newRightLon);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return plane.evaluateIsZero(x, y, z) &&
-        boundingPlane.isWithin(x, y, z);
-  }
-
-  @Override
-  public double getRadius() {
-    return Math.PI * 0.5;
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    return interiorPoint;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    return p.intersects(planetModel, plane, notablePoints, planePoints, bounds, boundingPlane);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    bounds
-      .addVerticalPlane(planetModel, longitude, plane, boundingPlane)
-      .addPoint(planetModel.NORTH_POLE).addPoint(planetModel.SOUTH_POLE);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    // Look for intersections.
-    if (path.intersects(plane, planePoints, boundingPlane))
-      return OVERLAPS;
-
-    if (path.isWithin(interiorPoint))
-      return CONTAINS;
-
-    return DISJOINT;
-  }
-
-  @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;
-    GeoDegenerateLongitudeSlice other = (GeoDegenerateLongitudeSlice) o;
-    return super.equals(other) && other.longitude == longitude;
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    long temp = Double.doubleToLongBits(longitude);
-    result = result * 31 + (int) (temp ^ (temp >>> 32));
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoDegenerateLongitudeSlice: {planetmodel="+planetModel+", longitude=" + longitude + "(" + longitude * 180.0 / Math.PI + ")}";
-  }
-}
-  
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegeneratePoint.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegeneratePoint.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegeneratePoint.java
deleted file mode 100644
index 63670d7..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegeneratePoint.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-    
-/**
- * This class represents a degenerate point bounding box.
- * It is not a simple GeoPoint because we must have the latitude and longitude.
- *
- * @lucene.internal
- */
-public class GeoDegeneratePoint extends GeoPoint implements GeoBBox, GeoCircle {
-  /** Current planet model, since we don't extend BasePlanetObject */
-  protected final PlanetModel planetModel;
-  /** Edge point is an area containing just this */
-  protected final GeoPoint[] edgePoints;
-
-  /** Constructor.
-   *@param planetModel is the planet model to use.
-   *@param lat is the latitude.
-   *@param lon is the longitude.
-   */
-  public GeoDegeneratePoint(final PlanetModel planetModel, final double lat, final double lon) {
-    super(planetModel, lat, lon);
-    this.planetModel = planetModel;
-    this.edgePoints = new GeoPoint[]{this};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    final double newTopLat = latitude + angle;
-    final double newBottomLat = latitude - angle;
-    final double newLeftLon = longitude - angle;
-    final double newRightLon = longitude + angle;
-    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane plane, final GeoPoint[] notablePoints, final Membership... bounds) {
-    // If not on the plane, no intersection
-    if (!plane.evaluateIsZero(this))
-      return false;
-
-    for (Membership m : bounds) {
-      if (!m.isWithin(this))
-        return false;
-    }
-    return true;
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    bounds.addPoint(this);
-  }
-
-  @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))
-      return false;
-    GeoDegeneratePoint other = (GeoDegeneratePoint) o;
-    return super.equals(other) && other.latitude == latitude && other.longitude == longitude;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoDegeneratePoint: {planetmodel="+planetModel+", lat=" + latitude + "(" + latitude * 180.0 / Math.PI + "), lon=" + longitude + "(" + longitude * 180.0 / Math.PI + ")}";
-  }
-
-  @Override
-  public boolean isWithin(final Vector point) {
-    return isWithin(point.x, point.y, point.z);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return x == this.x && y == this.y && z == this.z;
-  }
-
-  @Override
-  public double getRadius() {
-    return 0.0;
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    return this;
-  }
-
-  @Override
-  public int getRelationship(final GeoShape shape) {
-    if (shape.isWithin(this)) {
-      //System.err.println("Degenerate point "+this+" is WITHIN shape "+shape);
-      return CONTAINS;
-    }
-
-    //System.err.println("Degenerate point "+this+" is NOT within shape "+shape);
-    return DISJOINT;
-  }
-
-  @Override
-  public double computeDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
-    if (isWithin(x,y,z))
-      return 0.0;
-    return Double.MAX_VALUE;
-  }
-}
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateVerticalLine.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateVerticalLine.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateVerticalLine.java
deleted file mode 100644
index f21f774..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateVerticalLine.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Degenerate bounding box limited on two sides (top lat, bottom lat).
- *
- * @lucene.internal
- */
-public class GeoDegenerateVerticalLine extends GeoBaseBBox {
-  /** Top latitude of the vertical line */
-  protected final double topLat;
-  /** Bottom latitude of the vertical line */
-  protected final double bottomLat;
-  /** Longitude of the vertical line */
-  protected final double longitude;
-
-  /** Point at the upper end of the vertical line */
-  protected final GeoPoint UHC;
-  /** Point at the lower end of the vertical line */
-  protected final GeoPoint LHC;
-
-  /** Top end cutoff plane */
-  protected final SidedPlane topPlane;
-  /** Bottom end cutoff plane */
-  protected final SidedPlane bottomPlane;
-  /** Back-side cutoff plane */
-  protected final SidedPlane boundingPlane;
-  /** The vertical line plane */
-  protected final Plane plane;
-  /** Notable points for the line (end points) */
-  protected final GeoPoint[] planePoints;
-  /** A computed center point for the line */
-  protected final GeoPoint centerPoint;
-  /** A point that's on the line */
-  protected final GeoPoint[] edgePoints;
-
-  /**
-   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, longitude: {@code -PI -> PI}
-   */
-  public GeoDegenerateVerticalLine(final PlanetModel planetModel, final double topLat, final double bottomLat, final double longitude) {
-    super(planetModel);
-    // Argument checking
-    if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
-      throw new IllegalArgumentException("Top latitude out of range");
-    if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
-      throw new IllegalArgumentException("Bottom latitude out of range");
-    if (topLat < bottomLat)
-      throw new IllegalArgumentException("Top latitude less than bottom latitude");
-    if (longitude < -Math.PI || longitude > Math.PI)
-      throw new IllegalArgumentException("Longitude out of range");
-
-    this.topLat = topLat;
-    this.bottomLat = bottomLat;
-    this.longitude = longitude;
-
-    final double sinTopLat = Math.sin(topLat);
-    final double cosTopLat = Math.cos(topLat);
-    final double sinBottomLat = Math.sin(bottomLat);
-    final double cosBottomLat = Math.cos(bottomLat);
-    final double sinLongitude = Math.sin(longitude);
-    final double cosLongitude = Math.cos(longitude);
-
-    // Now build the two points
-    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);
-
-    final double middleLat = (topLat + bottomLat) * 0.5;
-    final double sinMiddleLat = Math.sin(middleLat);
-    final double cosMiddleLat = Math.cos(middleLat);
-
-    this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinLongitude, cosMiddleLat, cosLongitude);
-
-    this.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
-    this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
-
-    this.boundingPlane = new SidedPlane(centerPoint, -sinLongitude, cosLongitude);
-
-    this.planePoints = new GeoPoint[]{UHC, LHC};
-
-    this.edgePoints = new GeoPoint[]{centerPoint};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    final double newTopLat = topLat + angle;
-    final double newBottomLat = bottomLat - angle;
-    double newLeftLon = longitude - angle;
-    double newRightLon = longitude + angle;
-    double currentLonSpan = 2.0 * angle;
-    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
-      newLeftLon = -Math.PI;
-      newRightLon = Math.PI;
-    }
-    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return plane.evaluateIsZero(x, y, z) &&
-        boundingPlane.isWithin(x, y, z) &&
-        topPlane.isWithin(x, y, z) &&
-        bottomPlane.isWithin(x, y, z);
-  }
-
-  @Override
-  public double getRadius() {
-    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
-    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
-    // the distance to the right or left edge from the center.
-    final double topAngle = centerPoint.arcDistance(UHC);
-    final double bottomAngle = centerPoint.arcDistance(LHC);
-    return Math.max(topAngle, bottomAngle);
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    return centerPoint;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    return p.intersects(planetModel, plane, notablePoints, planePoints, bounds, boundingPlane, topPlane, bottomPlane);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    bounds.addVerticalPlane(planetModel, longitude, plane, boundingPlane, topPlane, bottomPlane)
-      .addPoint(UHC).addPoint(LHC);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    //System.err.println(this+" relationship to "+path);
-    if (path.intersects(plane, planePoints, boundingPlane, topPlane, bottomPlane)) {
-      //System.err.println(" overlaps");
-      return OVERLAPS;
-    }
-
-    if (path.isWithin(centerPoint)) {
-      //System.err.println(" contains");
-      return CONTAINS;
-    }
-
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @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;
-    GeoDegenerateVerticalLine other = (GeoDegenerateVerticalLine) o;
-    return super.equals(other) && other.UHC.equals(UHC) && other.LHC.equals(LHC);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + UHC.hashCode();
-    result = 31 * result + LHC.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoDegenerateVerticalLine: {longitude=" + longitude + "(" + longitude * 180.0 / Math.PI + "), toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + ")}";
-  }
-}
-  
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDistance.java
deleted file mode 100755
index 899a687..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDistance.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * 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 {
-  
-  // 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 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 distance.
-   */
-  public default double computeDistance(final DistanceStyle distanceStyle, final GeoPoint point) {
-    return computeDistance(distanceStyle, point.x, point.y, point.z);
-  }
-
-  /**
-   * 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 distance.
-   */
-  public double computeDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDistanceShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDistanceShape.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDistanceShape.java
deleted file mode 100755
index 1e82f48..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDistanceShape.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Distance shapes have capabilities of both geohashing and distance
- * computation (which also includes point membership determination).
- *
- * @lucene.experimental
- */
-public interface GeoDistanceShape extends GeoMembershipShape, GeoDistance {
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLatitudeZone.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLatitudeZone.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLatitudeZone.java
deleted file mode 100755
index 3fc4423..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLatitudeZone.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * This GeoBBox represents an area rectangle limited only in latitude.
- *
- * @lucene.internal
- */
-public class GeoLatitudeZone extends GeoBaseBBox {
-  /** The top latitude of the zone */
-  protected final double topLat;
-  /** The bottom latitude of the zone */
-  protected final double bottomLat;
-  /** Cosine of the top lat */
-  protected final double cosTopLat;
-  /** Cosine of the bottom lat */
-  protected final double cosBottomLat;
-  /** The top plane */
-  protected final SidedPlane topPlane;
-  /** The bottom plane */
-  protected final SidedPlane bottomPlane;
-  /** An interior point */
-  protected final GeoPoint interiorPoint;
-  /** Notable points (none) */
-  protected final static GeoPoint[] planePoints = new GeoPoint[0];
-
-  // We need two additional points because a latitude zone's boundaries don't intersect.  This is a very
-  // special case that most GeoBBox's do not have.
-  
-  /** Top boundary point */
-  protected final GeoPoint topBoundaryPoint;
-  /** Bottom boundary point */
-  protected final GeoPoint bottomBoundaryPoint;
-  /** A point on each distinct edge */
-  protected final GeoPoint[] edgePoints;
-
-  /** Constructor.
-   *@param planetModel is the planet model to use.
-   *@param topLat is the top latitude.
-   *@param bottomLat is the bottom latitude.
-   */
-  public GeoLatitudeZone(final PlanetModel planetModel, final double topLat, final double bottomLat) {
-    super(planetModel);
-    this.topLat = topLat;
-    this.bottomLat = bottomLat;
-
-    final double sinTopLat = Math.sin(topLat);
-    final double sinBottomLat = Math.sin(bottomLat);
-    this.cosTopLat = Math.cos(topLat);
-    this.cosBottomLat = Math.cos(bottomLat);
-
-    // Compute an interior point.  Pick one whose lat is between top and bottom.
-    final double middleLat = (topLat + bottomLat) * 0.5;
-    final double sinMiddleLat = Math.sin(middleLat);
-    this.interiorPoint = new GeoPoint(planetModel, sinMiddleLat, 0.0, Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 1.0);
-    this.topBoundaryPoint = new GeoPoint(planetModel, sinTopLat, 0.0, Math.sqrt(1.0 - sinTopLat * sinTopLat), 1.0);
-    this.bottomBoundaryPoint = new GeoPoint(planetModel, sinBottomLat, 0.0, Math.sqrt(1.0 - sinBottomLat * sinBottomLat), 1.0);
-
-    this.topPlane = new SidedPlane(interiorPoint, planetModel, sinTopLat);
-    this.bottomPlane = new SidedPlane(interiorPoint, planetModel, sinBottomLat);
-
-    this.edgePoints = new GeoPoint[]{topBoundaryPoint, bottomBoundaryPoint};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    final double newTopLat = topLat + angle;
-    final double newBottomLat = bottomLat - angle;
-    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, -Math.PI, Math.PI);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return topPlane.isWithin(x, y, z) &&
-        bottomPlane.isWithin(x, y, z);
-  }
-
-  @Override
-  public double getRadius() {
-    // This is a bit tricky.  I guess we should interpret this as meaning the angle of a circle that
-    // would contain all the bounding box points, when starting in the "center".
-    if (topLat > 0.0 && bottomLat < 0.0)
-      return Math.PI;
-    double maxCosLat = cosTopLat;
-    if (maxCosLat < cosBottomLat)
-      maxCosLat = cosBottomLat;
-    return maxCosLat * Math.PI;
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    // This is totally arbitrary and only a cartesian could agree with it.
-    return interiorPoint;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    return p.intersects(planetModel, topPlane, notablePoints, planePoints, bounds, bottomPlane) ||
-        p.intersects(planetModel, bottomPlane, notablePoints, planePoints, bounds, topPlane);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    bounds.noLongitudeBound()
-      .addHorizontalPlane(planetModel, topLat, topPlane)
-      .addHorizontalPlane(planetModel, bottomLat, bottomPlane);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    final int insideRectangle = isShapeInsideBBox(path);
-    if (insideRectangle == SOME_INSIDE)
-      return OVERLAPS;
-
-    final boolean topBoundaryInsideShape = path.isWithin(topBoundaryPoint);
-    final boolean bottomBoundaryInsideShape = path.isWithin(bottomBoundaryPoint);
-
-    if (topBoundaryInsideShape && !bottomBoundaryInsideShape ||
-        !topBoundaryInsideShape && bottomBoundaryInsideShape)
-      return OVERLAPS;
-
-    final boolean insideShape = topBoundaryInsideShape && bottomBoundaryInsideShape;
-
-    if (insideRectangle == ALL_INSIDE && insideShape)
-      return OVERLAPS;
-
-    // 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(topPlane, planePoints, bottomPlane) ||
-        path.intersects(bottomPlane, planePoints, topPlane))
-      return OVERLAPS;
-
-    // There is another case for latitude zones only.  This is when the boundaries of the shape all fit
-    // within the zone, but the shape includes areas outside the zone crossing a pole.
-    // In this case, the above "overlaps" check is insufficient.  We also need to check a point on either boundary
-    // whether it is within the shape.  If both such points are within, then CONTAINS is the right answer.  If
-    // one such point is within, then OVERLAPS is the right answer.
-
-    if (insideShape)
-      return CONTAINS;
-
-    if (insideRectangle == ALL_INSIDE)
-      return WITHIN;
-
-    return DISJOINT;
-  }
-
-  @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;
-    GeoLatitudeZone other = (GeoLatitudeZone) o;
-    return super.equals(other) && other.topBoundaryPoint.equals(topBoundaryPoint) && other.bottomBoundaryPoint.equals(bottomBoundaryPoint);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + topBoundaryPoint.hashCode();
-    result = 31 * result + bottomBoundaryPoint.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoLatitudeZone: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + ")}";
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLongitudeSlice.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLongitudeSlice.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLongitudeSlice.java
deleted file mode 100755
index f5de7e7..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLongitudeSlice.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Bounding box limited on left and right.
- * The left-right maximum extent for this shape is PI; for anything larger, use
- * {@link GeoWideLongitudeSlice}.
- *
- * @lucene.internal
- */
-public class GeoLongitudeSlice extends GeoBaseBBox {
-  /** The left longitude of the slice */
-  protected final double leftLon;
-  /** The right longitude of the slice */
-  protected final double rightLon;
-  /** The left plane of the slice */
-  protected final SidedPlane leftPlane;
-  /** The right plane of the slice */
-  protected final SidedPlane rightPlane;
-  /** The notable points for the slice (north and south poles) */
-  protected final GeoPoint[] planePoints;
-  /** The center point of the slice */
-  protected final GeoPoint centerPoint;
-  /** A point on the edge of the slice */
-  protected final GeoPoint[] edgePoints;
-
-  /**
-   * Accepts only values in the following ranges: lon: {@code -PI -> PI}
-   *@param planetModel is the planet model.
-   *@param leftLon is the left longitude of the slice.
-   *@param rightLon is the right longitude of the slice.
-   */
-  public GeoLongitudeSlice(final PlanetModel planetModel, final double leftLon, double rightLon) {
-    super(planetModel);
-    // Argument checking
-    if (leftLon < -Math.PI || leftLon > Math.PI)
-      throw new IllegalArgumentException("Left longitude out of range");
-    if (rightLon < -Math.PI || rightLon > Math.PI)
-      throw new IllegalArgumentException("Right longitude out of range");
-    double extent = rightLon - leftLon;
-    if (extent < 0.0) {
-      extent += 2.0 * Math.PI;
-    }
-    if (extent > Math.PI)
-      throw new IllegalArgumentException("Width of rectangle too great");
-
-    this.leftLon = leftLon;
-    this.rightLon = rightLon;
-
-    final double sinLeftLon = Math.sin(leftLon);
-    final double cosLeftLon = Math.cos(leftLon);
-    final double sinRightLon = Math.sin(rightLon);
-    final double cosRightLon = Math.cos(rightLon);
-
-    // Normalize
-    while (leftLon > rightLon) {
-      rightLon += Math.PI * 2.0;
-    }
-    final double middleLon = (leftLon + rightLon) * 0.5;
-    this.centerPoint = new GeoPoint(planetModel, 0.0, middleLon);
-
-    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
-    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
-
-    this.planePoints = new GeoPoint[]{planetModel.NORTH_POLE, planetModel.SOUTH_POLE};
-    this.edgePoints = new GeoPoint[]{planetModel.NORTH_POLE};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    // Figuring out when we escalate to a special case requires some prefiguring
-    double currentLonSpan = rightLon - leftLon;
-    if (currentLonSpan < 0.0)
-      currentLonSpan += Math.PI * 2.0;
-    double newLeftLon = leftLon - angle;
-    double newRightLon = rightLon + angle;
-    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
-      newLeftLon = -Math.PI;
-      newRightLon = Math.PI;
-    }
-    return GeoBBoxFactory.makeGeoBBox(planetModel, Math.PI * 0.5, -Math.PI * 0.5, newLeftLon, newRightLon);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return leftPlane.isWithin(x, y, z) &&
-        rightPlane.isWithin(x, y, z);
-  }
-
-  @Override
-  public double getRadius() {
-    // Compute the extent and divide by two
-    double extent = rightLon - leftLon;
-    if (extent < 0.0)
-      extent += Math.PI * 2.0;
-    return Math.max(Math.PI * 0.5, extent * 0.5);
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    return centerPoint;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    return p.intersects(planetModel, leftPlane, notablePoints, planePoints, bounds, rightPlane) ||
-        p.intersects(planetModel, rightPlane, notablePoints, planePoints, bounds, leftPlane);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    bounds
-      .addVerticalPlane(planetModel, leftLon, leftPlane, rightPlane)
-      .addVerticalPlane(planetModel, rightLon, rightPlane, leftPlane)
-      .addPoint(planetModel.NORTH_POLE)
-      .addPoint(planetModel.SOUTH_POLE);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    final int insideRectangle = isShapeInsideBBox(path);
-    if (insideRectangle == SOME_INSIDE)
-      return OVERLAPS;
-
-    final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
-
-    if (insideRectangle == ALL_INSIDE && insideShape)
-      return OVERLAPS;
-
-    if (path.intersects(leftPlane, planePoints, rightPlane) ||
-        path.intersects(rightPlane, planePoints, leftPlane)) {
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE) {
-      return WITHIN;
-    }
-
-    if (insideShape) {
-      return CONTAINS;
-    }
-
-    return DISJOINT;
-  }
-
-  @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;
-    GeoLongitudeSlice other = (GeoLongitudeSlice) o;
-    return super.equals(other) && other.leftLon == leftLon && other.rightLon == rightLon;
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    long temp = Double.doubleToLongBits(leftLon);
-    result = 31 * result + (int) (temp ^ (temp >>> 32));
-    temp = Double.doubleToLongBits(rightLon);
-    result = 31 * result + (int) (temp ^ (temp >>> 32));
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoLongitudeSlice: {planetmodel="+planetModel+", leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
-  }
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoMembershipShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoMembershipShape.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoMembershipShape.java
deleted file mode 100755
index 54b2551..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoMembershipShape.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Membership shapes have capabilities of both geohashing and membership
- * determination.
- *
- * @lucene.experimental
- */
-public interface GeoMembershipShape extends GeoShape, GeoOutsideDistance, Membership {
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthLatitudeZone.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthLatitudeZone.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthLatitudeZone.java
deleted file mode 100644
index 43338bb..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthLatitudeZone.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * This GeoBBox represents an area rectangle limited only in south latitude.
- *
- * @lucene.internal
- */
-public class GeoNorthLatitudeZone extends GeoBaseBBox {
-  /** The bottom latitude of the zone */
-  protected final double bottomLat;
-  /** Cosine of the bottom latitude of the zone */
-  protected final double cosBottomLat;
-  /** The bottom plane of the zone */
-  protected final SidedPlane bottomPlane;
-  /** An interior point of the zone */
-  protected final GeoPoint interiorPoint;
-  /** Notable points: none */
-  protected final static GeoPoint[] planePoints = new GeoPoint[0];
-  /** A point on the bottom boundary */
-  protected final GeoPoint bottomBoundaryPoint;
-  /** A reference to the point on the boundary */
-  protected final GeoPoint[] edgePoints;
-
-  /** Constructor.
-   *@param planetModel is the planet model.
-   *@param bottomLat is the bottom latitude.
-   */
-  public GeoNorthLatitudeZone(final PlanetModel planetModel, final double bottomLat) {
-    super(planetModel);
-    this.bottomLat = bottomLat;
-
-    final double sinBottomLat = Math.sin(bottomLat);
-    this.cosBottomLat = Math.cos(bottomLat);
-
-    // Compute an interior point.  Pick one whose lat is between top and bottom.
-    final double middleLat = (Math.PI * 0.5 + bottomLat) * 0.5;
-    final double sinMiddleLat = Math.sin(middleLat);
-    this.interiorPoint = new GeoPoint(planetModel, sinMiddleLat, 0.0, Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 1.0);
-    this.bottomBoundaryPoint = new GeoPoint(planetModel, sinBottomLat, 0.0, Math.sqrt(1.0 - sinBottomLat * sinBottomLat), 1.0);
-
-    this.bottomPlane = new SidedPlane(interiorPoint, planetModel, sinBottomLat);
-
-    this.edgePoints = new GeoPoint[]{bottomBoundaryPoint};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    final double newTopLat = Math.PI * 0.5;
-    final double newBottomLat = bottomLat - angle;
-    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, -Math.PI, Math.PI);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return
-        bottomPlane.isWithin(x, y, z);
-  }
-
-  @Override
-  public double getRadius() {
-    // This is a bit tricky.  I guess we should interpret this as meaning the angle of a circle that
-    // would contain all the bounding box points, when starting in the "center".
-    if (bottomLat < 0.0)
-      return Math.PI;
-    double maxCosLat = cosBottomLat;
-    return maxCosLat * Math.PI;
-  }
-
-  @Override
-  public GeoPoint getCenter() {
-    return interiorPoint;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    return
-        p.intersects(planetModel, bottomPlane, notablePoints, planePoints, bounds);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    bounds
-      .addHorizontalPlane(planetModel, bottomLat, bottomPlane);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    final int insideRectangle = isShapeInsideBBox(path);
-    if (insideRectangle == SOME_INSIDE)
-      return OVERLAPS;
-
-    final boolean insideShape = path.isWithin(bottomBoundaryPoint);
-
-    if (insideRectangle == ALL_INSIDE && insideShape)
-      return OVERLAPS;
-
-    // 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))
-      return OVERLAPS;
-
-    // There is another case for latitude zones only.  This is when the boundaries of the shape all fit
-    // within the zone, but the shape includes areas outside the zone crossing a pole.
-    // In this case, the above "overlaps" check is insufficient.  We also need to check a point on either boundary
-    // whether it is within the shape.  If both such points are within, then CONTAINS is the right answer.  If
-    // one such point is within, then OVERLAPS is the right answer.
-
-    if (insideShape)
-      return CONTAINS;
-
-    if (insideRectangle == ALL_INSIDE)
-      return WITHIN;
-
-    return DISJOINT;
-  }
-
-  @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;
-    GeoNorthLatitudeZone other = (GeoNorthLatitudeZone) o;
-    return super.equals(other) && other.bottomBoundaryPoint.equals(bottomBoundaryPoint);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + bottomBoundaryPoint.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoNorthLatitudeZone: {planetmodel="+planetModel+", bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + ")}";
-  }
-}
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthRectangle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthRectangle.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthRectangle.java
deleted file mode 100644
index 66b9480..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthRectangle.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * 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
- * {@link GeoWideNorthRectangle}.
- *
- * @lucene.internal
- */
-public class GeoNorthRectangle extends GeoBaseBBox {
-  /** The bottom latitude of the rectangle */
-  protected final double bottomLat;
-  /** The left longitude */
-  protected final double leftLon;
-  /** The right longitude */
-  protected final double rightLon;
-  /** Cosine of the middle latitude */
-  protected final double cosMiddleLat;
-  /** Lower right hand corner point */
-  protected final GeoPoint LRHC;
-  /** Lower left hand corner point */
-  protected final GeoPoint LLHC;
-  /** Bottom edge plane */
-  protected final SidedPlane bottomPlane;
-  /** Left-side plane */
-  protected final SidedPlane leftPlane;
-  /** Right-side plane */
-  protected final SidedPlane rightPlane;
-  /** Bottom plane notable points */
-  protected final GeoPoint[] bottomPlanePoints;
-  /** Left plane notable points */
-  protected final GeoPoint[] leftPlanePoints;
-  /** Right plane notable points */
-  protected final GeoPoint[] rightPlanePoints;
-  /** Center point */
-  protected final GeoPoint centerPoint;
-  /** A point on the edge */
-  protected final GeoPoint[] edgePoints;
-
-  /**
-   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
-   *@param planetModel is the planet model.
-   *@param bottomLat is the bottom latitude.
-   *@param leftLon is the left longitude.
-   *@param rightLon is the right longitude.
-   */
-  public GeoNorthRectangle(final PlanetModel planetModel, final double bottomLat, final double leftLon, double rightLon) {
-    super(planetModel);
-    // Argument checking
-    if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
-      throw new IllegalArgumentException("Bottom latitude out of range");
-    if (leftLon < -Math.PI || leftLon > Math.PI)
-      throw new IllegalArgumentException("Left longitude out of range");
-    if (rightLon < -Math.PI || rightLon > Math.PI)
-      throw new IllegalArgumentException("Right longitude out of range");
-    double extent = rightLon - leftLon;
-    if (extent < 0.0) {
-      extent += 2.0 * Math.PI;
-    }
-    if (extent > Math.PI)
-      throw new IllegalArgumentException("Width of rectangle too great");
-
-    this.bottomLat = bottomLat;
-    this.leftLon = leftLon;
-    this.rightLon = rightLon;
-
-    final double sinBottomLat = Math.sin(bottomLat);
-    final double cosBottomLat = Math.cos(bottomLat);
-    final double sinLeftLon = Math.sin(leftLon);
-    final double cosLeftLon = Math.cos(leftLon);
-    final double sinRightLon = Math.sin(rightLon);
-    final double cosRightLon = Math.cos(rightLon);
-
-    // Now build the points
-    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);
-    this.cosMiddleLat = Math.cos(middleLat);
-    // Normalize
-    while (leftLon > rightLon) {
-      rightLon += Math.PI * 2.0;
-    }
-    final double middleLon = (leftLon + rightLon) * 0.5;
-    final double sinMiddleLon = Math.sin(middleLon);
-    final double cosMiddleLon = Math.cos(middleLon);
-
-    this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
-
-    this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
-    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
-    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
-
-    this.bottomPlanePoints = new GeoPoint[]{LLHC, LRHC};
-    this.leftPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LLHC};
-    this.rightPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LRHC};
-
-    this.edgePoints = new GeoPoint[]{planetModel.NORTH_POLE};
-  }
-
-  @Override
-  public GeoBBox expand(final double angle) {
-    final double newTopLat = Math.PI * 0.5;
-    final double newBottomLat = bottomLat - angle;
-    // Figuring out when we escalate to a special case requires some prefiguring
-    double currentLonSpan = rightLon - leftLon;
-    if (currentLonSpan < 0.0)
-      currentLonSpan += Math.PI * 2.0;
-    double newLeftLon = leftLon - angle;
-    double newRightLon = rightLon + angle;
-    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
-      newLeftLon = -Math.PI;
-      newRightLon = Math.PI;
-    }
-    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return
-        bottomPlane.isWithin(x, y, z) &&
-            leftPlane.isWithin(x, y, z) &&
-            rightPlane.isWithin(x, y, z);
-  }
-
-  @Override
-  public double getRadius() {
-    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
-    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
-    // the distance to the right or left edge from the center.
-    final double centerAngle = (rightLon - (rightLon + leftLon) * 0.5) * cosMiddleLat;
-    final double bottomAngle = centerPoint.arcDistance(LLHC);
-    return Math.max(centerAngle, bottomAngle);
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-
-  /**
-   * Returns the center of a circle into which the area will be inscribed.
-   *
-   * @return the center.
-   */
-  @Override
-  public GeoPoint getCenter() {
-    return centerPoint;
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    return
-        p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, leftPlane, rightPlane) ||
-            p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, bottomPlane) ||
-            p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, bottomPlane);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    super.getBounds(bounds);
-    bounds
-      .addHorizontalPlane(planetModel, bottomLat, bottomPlane, leftPlane, rightPlane)
-      .addVerticalPlane(planetModel, leftLon, leftPlane, bottomPlane, rightPlane)
-      .addVerticalPlane(planetModel, rightLon, rightPlane, bottomPlane, leftPlane)
-      .addPoint(LLHC).addPoint(LRHC).addPoint(planetModel.NORTH_POLE);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    //System.err.println(this+" getrelationship with "+path);
-    final int insideRectangle = isShapeInsideBBox(path);
-    if (insideRectangle == SOME_INSIDE) {
-      //System.err.println(" some inside");
-      return OVERLAPS;
-    }
-
-    final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
-
-    if (insideRectangle == ALL_INSIDE && insideShape) {
-      //System.err.println(" inside of each other");
-      return OVERLAPS;
-    }
-
-    if (
-        path.intersects(bottomPlane, bottomPlanePoints, leftPlane, rightPlane) ||
-            path.intersects(leftPlane, leftPlanePoints, bottomPlane, rightPlane) ||
-            path.intersects(rightPlane, rightPlanePoints, leftPlane, bottomPlane)) {
-      //System.err.println(" edges intersect");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE) {
-      //System.err.println(" shape inside rectangle");
-      return WITHIN;
-    }
-
-    if (insideShape) {
-      //System.err.println(" shape contains rectangle");
-      return CONTAINS;
-    }
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @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;
-    GeoNorthRectangle other = (GeoNorthRectangle) o;
-    return super.equals(other) && other.LLHC.equals(LLHC) && other.LRHC.equals(LRHC);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + LLHC.hashCode();
-    result = 31 * result + LRHC.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "GeoNorthRectangle: {planetmodel="+planetModel+", bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
-  }
-}
-  
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoOutsideDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoOutsideDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoOutsideDistance.java
deleted file mode 100644
index c1d784d..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoOutsideDistance.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Implemented by Geo3D shapes that can compute the distance from a point to the closest outside edge.
- *
- * @lucene.experimental
- */
-public interface GeoOutsideDistance extends Membership {
-  
-  // The following methods compute distances from the shape to a point
-  // expected to be OUTSIDE the shape.  Typically a value of 0.0
-  // is returned for points that happen to be within the shape.
-  
-  /**
-   * Compute this shape's distance to the GeoPoint.
-   * A return value of 0.0 should be returned for
-   * points inside of the shape.
-   * @param distanceStyle is the distance style.
-   * @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);
-  }
-
-  /**
-   * Compute this shape's distance to the GeoPoint.
-   * A return value of 0.0 should be returned for
-   * points inside of the shape.
-   * @param distanceStyle is the distance style.
-   * @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 distance.
-   */
-  public double computeOutsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
-
-}
-


[45/50] [abbrv] lucene-solr git commit: SOLR-8799: Update CHANGES.txt

Posted by no...@apache.org.
SOLR-8799: Update CHANGES.txt


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

Branch: refs/heads/apiv2
Commit: 02523d5b6d7a4416265c4a36289b3dcb497ed6a6
Parents: 56ad6e5
Author: jbernste <jb...@apache.org>
Authored: Tue Mar 8 15:25:52 2016 -0500
Committer: jbernste <jb...@apache.org>
Committed: Tue Mar 8 15:25:52 2016 -0500

----------------------------------------------------------------------
 solr/CHANGES.txt | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/02523d5b/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index d094b58..dc7c45f 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -408,6 +408,8 @@ Other Changes
 * SOLR-8766: Remove deprecated <admin> tag in solrconfig.xml and support for admin/gettableFiles
   (noble, Jason Gerlowski, Varun Thacker)
 
+* SOLR-8799: Improve error message when tuple can't be read by SolrJ JDBC (Kevin Risden, Joel Bernstein)
+
 ==================  5.5.1 ==================
 
 Bug Fixes


[18/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PlanetModel.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PlanetModel.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PlanetModel.java
deleted file mode 100644
index 395fa15..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PlanetModel.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Holds mathematical constants associated with the model of a planet.
- * @lucene.experimental
- */
-public class PlanetModel {
-  
-  /** Planet model corresponding to sphere. */
-  public static final PlanetModel SPHERE = new PlanetModel(1.0,1.0);
-
-  /** Mean radius */
-  public static final double WGS84_MEAN = 6371009.0;
-  /** Polar radius */
-  public static final double WGS84_POLAR = 6356752.314245;
-  /** Equatorial radius */
-  public static final double WGS84_EQUATORIAL = 6378137.0;
-  /** Planet model corresponding to WGS84 */
-  public static final PlanetModel WGS84 = new PlanetModel(WGS84_EQUATORIAL/WGS84_MEAN,
-    WGS84_POLAR/WGS84_MEAN);
-
-  // Surface of the planet:
-  // x^2/a^2 + y^2/b^2 + z^2/c^2 = 1.0
-  // Scaling factors are a,b,c.  geo3d can only support models where a==b, so use ab instead.
-  
-  /** The x/y scaling factor */
-  public final double ab;
-  /** The z scaling factor */
-  public final double c;
-  /** The inverse of ab */
-  public final double inverseAb;
-  /** The inverse of c */
-  public final double inverseC;
-  /** The square of the inverse of ab */
-  public final double inverseAbSquared;
-  /** The square of the inverse of c */
-  public final double inverseCSquared;
-  /** The flattening value */
-  public final double flattening;
-  /** The square ratio */
-  public final double squareRatio;
-  
-  // We do NOT include radius, because all computations in geo3d are in radians, not meters.
-  
-  // Compute north and south pole for planet model, since these are commonly used.
-  
-  /** North pole */
-  public final GeoPoint NORTH_POLE;
-  /** South pole */
-  public final GeoPoint SOUTH_POLE;
-  /** Min X pole */
-  public final GeoPoint MIN_X_POLE;
-  /** Max X pole */
-  public final GeoPoint MAX_X_POLE;
-  /** Min Y pole */
-  public final GeoPoint MIN_Y_POLE;
-  /** Max Y pole */
-  public final GeoPoint MAX_Y_POLE;
-  
-  /** Constructor.
-   * @param ab is the x/y scaling factor.
-   * @param c is the z scaling factor.
-   */
-  public PlanetModel(final double ab, final double c) {
-    this.ab = ab;
-    this.c = c;
-    this.inverseAb = 1.0 / ab;
-    this.inverseC = 1.0 / c;
-    this.flattening = (ab - c) * inverseAb;
-    this.squareRatio = (ab * ab - c * c) / (c * c);
-    this.inverseAbSquared = inverseAb * inverseAb;
-    this.inverseCSquared = inverseC * inverseC;
-    this.NORTH_POLE = new GeoPoint(c, 0.0, 0.0, 1.0, Math.PI * 0.5, 0.0);
-    this.SOUTH_POLE = new GeoPoint(c, 0.0, 0.0, -1.0, -Math.PI * 0.5, 0.0);
-    this.MIN_X_POLE = new GeoPoint(ab, -1.0, 0.0, 0.0, 0.0, -Math.PI);
-    this.MAX_X_POLE = new GeoPoint(ab, 1.0, 0.0, 0.0, 0.0, 0.0);
-    this.MIN_Y_POLE = new GeoPoint(ab, 0.0, -1.0, 0.0, 0.0, -Math.PI * 0.5);
-    this.MAX_Y_POLE = new GeoPoint(ab, 0.0, 1.0, 0.0, 0.0, Math.PI * 0.5);
-  }
-  
-  /** Find the minimum magnitude of all points on the ellipsoid.
-   * @return the minimum magnitude for the planet.
-   */
-  public double getMinimumMagnitude() {
-    return Math.min(this.ab, this.c);
-  }
-
-  /** Find the maximum magnitude of all points on the ellipsoid.
-   * @return the maximum magnitude for the planet.
-   */
-  public double getMaximumMagnitude() {
-    return Math.max(this.ab, this.c);
-  }
-  
-  /** Find the minimum x value.
-   *@return the minimum X value.
-   */
-  public double getMinimumXValue() {
-    return -this.ab;
-  }
-  
-  /** Find the maximum x value.
-   *@return the maximum X value.
-   */
-  public double getMaximumXValue() {
-    return this.ab;
-  }
-
-  /** Find the minimum y value.
-   *@return the minimum Y value.
-   */
-  public double getMinimumYValue() {
-    return -this.ab;
-  }
-  
-  /** Find the maximum y value.
-   *@return the maximum Y value.
-   */
-  public double getMaximumYValue() {
-    return this.ab;
-  }
-  
-  /** Find the minimum z value.
-   *@return the minimum Z value.
-   */
-  public double getMinimumZValue() {
-    return -this.c;
-  }
-  
-  /** Find the maximum z value.
-   *@return the maximum Z value.
-   */
-  public double getMaximumZValue() {
-    return this.c;
-  }
-
-  /** Check if point is on surface.
-   * @param v is the point to check.
-   * @return true if the point is on the planet surface.
-   */
-  public boolean pointOnSurface(final Vector v) {
-    return pointOnSurface(v.x, v.y, v.z);
-  }
-  
-  /** Check if point is on surface.
-   * @param x is the x coord.
-   * @param y is the y coord.
-   * @param z is the z coord.
-   */
-  public boolean pointOnSurface(final double x, final double y, final double z) {
-    // Equation of planet surface is:
-    // x^2 / a^2 + y^2 / b^2 + z^2 / c^2 - 1 = 0
-    return Math.abs(x * x * inverseAb * inverseAb + y * y * inverseAb * inverseAb + z * z * inverseC * inverseC - 1.0) < Vector.MINIMUM_RESOLUTION;
-  }
-
-  /** Check if point is outside surface.
-   * @param v is the point to check.
-   * @return true if the point is outside the planet surface.
-   */
-  public boolean pointOutside(final Vector v) {
-    return pointOutside(v.x, v.y, v.z);
-  }
-  
-  /** Check if point is outside surface.
-   * @param x is the x coord.
-   * @param y is the y coord.
-   * @param z is the z coord.
-   */
-  public boolean pointOutside(final double x, final double y, final double z) {
-    // Equation of planet surface is:
-    // x^2 / a^2 + y^2 / b^2 + z^2 / c^2 - 1 = 0
-    return (x * x + y * y) * inverseAb * inverseAb + z * z * inverseC * inverseC - 1.0 > Vector.MINIMUM_RESOLUTION;
-  }
-  
-  /** Compute surface distance between two points.
-   * @param p1 is the first point.
-   * @param p2 is the second point.
-   * @return the adjusted angle, when multiplied by the mean earth radius, yields a surface distance.  This will differ
-   * from GeoPoint.arcDistance() only when the planet model is not a sphere. @see {@link org.apache.lucene.geo3d.GeoPoint#arcDistance(GeoPoint)}
-   */
-  public double surfaceDistance(final GeoPoint p1, final GeoPoint p2) {
-    final double latA = p1.getLatitude();
-    final double lonA = p1.getLongitude();
-    final double latB = p2.getLatitude();
-    final double lonB = p2.getLongitude();
-
-    final double L = lonB - lonA;
-    final double oF = 1.0 - this.flattening;
-    final double U1 = Math.atan(oF * Math.tan(latA));
-    final double U2 = Math.atan(oF * Math.tan(latB));
-    final double sU1 = Math.sin(U1);
-    final double cU1 = Math.cos(U1);
-    final double sU2 = Math.sin(U2);
-    final double cU2 = Math.cos(U2);
-
-    double sigma, sinSigma, cosSigma;
-    double cos2Alpha, cos2SigmaM;
-    
-    double lambda = L;
-    double iters = 100;
-
-    do {
-      final double sinLambda = Math.sin(lambda);
-      final double cosLambda = Math.cos(lambda);
-      sinSigma = Math.sqrt((cU2 * sinLambda) * (cU2 * sinLambda) + (cU1 * sU2 - sU1 * cU2 * cosLambda)
-          * (cU1 * sU2 - sU1 * cU2 * cosLambda));
-      if (Math.abs(sinSigma) < Vector.MINIMUM_RESOLUTION)
-        return 0.0;
-
-      cosSigma = sU1 * sU2 + cU1 * cU2 * cosLambda;
-      sigma = Math.atan2(sinSigma, cosSigma);
-      final double sinAlpha = cU1 * cU2 * sinLambda / sinSigma;
-      cos2Alpha = 1.0 - sinAlpha * sinAlpha;
-      cos2SigmaM = cosSigma - 2.0 * sU1 * sU2 / cos2Alpha;
-
-      final double c = this.flattening * 0.625 * cos2Alpha * (4.0 + this.flattening * (4.0 - 3.0 * cos2Alpha));
-      final double lambdaP = lambda;
-      lambda = L + (1.0 - c) * this.flattening * sinAlpha * (sigma + c * sinSigma * (cos2SigmaM + c * cosSigma *
-          (-1.0 + 2.0 * cos2SigmaM * cos2SigmaM)));
-      if (Math.abs(lambda - lambdaP) < Vector.MINIMUM_RESOLUTION)
-        break;
-    } while (--iters > 0);
-
-    if (iters == 0)
-      return 0.0;
-
-    final double uSq = cos2Alpha * this.squareRatio;
-    final double A = 1.0 + uSq * 0.00006103515625 * (4096.0 + uSq * (-768.0 + uSq * (320.0 - 175.0 * uSq)));
-    final double B = uSq * 0.0009765625 * (256.0 + uSq * (-128.0 + uSq * (74.0 - 47.0 * uSq)));
-    final double deltaSigma = B * sinSigma * (cos2SigmaM + B * 0.25 * (cosSigma * (-1.0 + 2.0 * cos2SigmaM * cos2SigmaM) - B * 0.16666666666666666666667 * cos2SigmaM
-            * (-3.0 + 4.0 * sinSigma * sinSigma) * (-3.0 + 4.0 * cos2SigmaM * cos2SigmaM)));
-
-    return this.c * A * (sigma - deltaSigma);
-  }
-
-  @Override
-  public boolean equals(final Object o) {
-    if (!(o instanceof PlanetModel))
-      return false;
-    final PlanetModel other = (PlanetModel)o;
-    return ab == other.ab && c == other.c;
-  }
-  
-  @Override
-  public int hashCode() {
-    return Double.hashCode(ab) + Double.hashCode(c);
-  }
-  
-  @Override
-  public String toString() {
-    if (this.equals(SPHERE)) {
-      return "PlanetModel.SPHERE";
-    } else if (this.equals(WGS84)) {
-      return "PlanetModel.WGS84";
-    } else {
-      return "PlanetModel(ab="+ab+" c="+c+")";
-    }
-  }
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PointInGeo3DShapeQuery.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PointInGeo3DShapeQuery.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PointInGeo3DShapeQuery.java
deleted file mode 100644
index 9e2132d..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PointInGeo3DShapeQuery.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-import java.io.IOException;
-
-import org.apache.lucene.index.PointValues.IntersectVisitor;
-import org.apache.lucene.index.PointValues;
-import org.apache.lucene.index.PointValues.Relation;
-import org.apache.lucene.index.LeafReader;
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.search.ConstantScoreScorer;
-import org.apache.lucene.search.ConstantScoreWeight;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.Scorer;
-import org.apache.lucene.search.Weight;
-import org.apache.lucene.util.DocIdSetBuilder;
-import org.apache.lucene.util.NumericUtils;
-
-/** Finds all previously indexed points that fall within the specified polygon.
- *
- * <p>The field must be indexed using {@link Geo3DPoint}.
- *
- * @lucene.experimental */
-
-class PointInGeo3DShapeQuery extends Query {
-  final String field;
-  final GeoShape shape;
-
-  /** The lats/lons must be clockwise or counter-clockwise. */
-  public PointInGeo3DShapeQuery(String field, GeoShape shape) {
-    this.field = field;
-    this.shape = shape;
-
-    if (shape instanceof BasePlanetObject) {
-      BasePlanetObject planetObject = (BasePlanetObject) shape;
-      if (planetObject.getPlanetModel().equals(PlanetModel.WGS84) == false) {
-        throw new IllegalArgumentException("this qurey requires PlanetModel.WGS84, but got: " + planetObject.getPlanetModel());
-      }
-    }
-  }
-
-  @Override
-  public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
-
-    // I don't use RandomAccessWeight here: it's no good to approximate with "match all docs"; this is an inverted structure and should be
-    // used in the first pass:
-
-    return new ConstantScoreWeight(this) {
-
-      @Override
-      public Scorer scorer(LeafReaderContext context) throws IOException {
-        LeafReader reader = context.reader();
-        PointValues values = reader.getPointValues();
-        if (values == null) {
-          return null;
-        }
-
-        /*
-        XYZBounds bounds = new XYZBounds();
-        shape.getBounds(bounds);
-
-        final double planetMax = planetModel.getMaximumMagnitude();
-        if (planetMax != treeDV.planetMax) {
-          throw new IllegalStateException(planetModel + " is not the same one used during indexing: planetMax=" + planetMax + " vs indexing planetMax=" + treeDV.planetMax);
-        }
-        */
-
-        /*
-        GeoArea xyzSolid = GeoAreaFactory.makeGeoArea(planetModel,
-                                                      bounds.getMinimumX(),
-                                                      bounds.getMaximumX(),
-                                                      bounds.getMinimumY(),
-                                                      bounds.getMaximumY(),
-                                                      bounds.getMinimumZ(),
-                                                      bounds.getMaximumZ());
-
-        assert xyzSolid.getRelationship(shape) == GeoArea.WITHIN || xyzSolid.getRelationship(shape) == GeoArea.OVERLAPS: "expected WITHIN (1) or OVERLAPS (2) but got " + xyzSolid.getRelationship(shape) + "; shape="+shape+"; XYZSolid="+xyzSolid;
-        */
-
-        double planetMax = PlanetModel.WGS84.getMaximumMagnitude();
-
-        DocIdSetBuilder result = new DocIdSetBuilder(reader.maxDoc());
-
-        values.intersect(field,
-                         new IntersectVisitor() {
-
-                           @Override
-                           public void visit(int docID) {
-                             result.add(docID);
-                           }
-
-                           @Override
-                           public void visit(int docID, byte[] packedValue) {
-                             assert packedValue.length == 12;
-                             double x = Geo3DPoint.decodeDimension(packedValue, 0);
-                             double y = Geo3DPoint.decodeDimension(packedValue, Integer.BYTES);
-                             double z = Geo3DPoint.decodeDimension(packedValue, 2 * Integer.BYTES);
-                             if (shape.isWithin(x, y, z)) {
-                               result.add(docID);
-                             }
-                           }
-
-                           @Override
-                           public Relation compare(byte[] minPackedValue, byte[] maxPackedValue) {
-                             // Because the dimensional format operates in quantized (64 bit -> 32 bit) space, and the cell bounds
-                             // here are inclusive, we need to extend the bounds to the largest un-quantized values that
-                             // could quantize into these bounds.  The encoding (Geo3DUtil.encodeValue) does
-                             // a Math.round from double to long, so e.g. 1.4 -> 1, and -1.4 -> -1:
-                             double xMin = Geo3DUtil.decodeValueMin(planetMax, NumericUtils.sortableBytesToInt(minPackedValue, 0));
-                             double xMax = Geo3DUtil.decodeValueMax(planetMax, NumericUtils.sortableBytesToInt(maxPackedValue, 0));
-                             double yMin = Geo3DUtil.decodeValueMin(planetMax, NumericUtils.sortableBytesToInt(minPackedValue, 1 * Integer.BYTES));
-                             double yMax = Geo3DUtil.decodeValueMax(planetMax, NumericUtils.sortableBytesToInt(maxPackedValue, 1 * Integer.BYTES));
-                             double zMin = Geo3DUtil.decodeValueMin(planetMax, NumericUtils.sortableBytesToInt(minPackedValue, 2 * Integer.BYTES));
-                             double zMax = Geo3DUtil.decodeValueMax(planetMax, NumericUtils.sortableBytesToInt(maxPackedValue, 2 * Integer.BYTES));
-
-                             //System.out.println("  compare: x=" + cellXMin + "-" + cellXMax + " y=" + cellYMin + "-" + cellYMax + " z=" + cellZMin + "-" + cellZMax);
-                             assert xMin <= xMax;
-                             assert yMin <= yMax;
-                             assert zMin <= zMax;
-
-                             GeoArea xyzSolid = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84, xMin, xMax, yMin, yMax, zMin, zMax);
-
-                             switch(xyzSolid.getRelationship(shape)) {
-                             case GeoArea.CONTAINS:
-                               // Shape fully contains the cell
-                               //System.out.println("    inside");
-                               return Relation.CELL_INSIDE_QUERY;
-                             case GeoArea.OVERLAPS:
-                               // They do overlap but neither contains the other:
-                               //System.out.println("    crosses1");
-                               return Relation.CELL_CROSSES_QUERY;
-                             case GeoArea.WITHIN:
-                               // Cell fully contains the shape:
-                               //System.out.println("    crosses2");
-                               // return Relation.SHAPE_INSIDE_CELL;
-                               return Relation.CELL_CROSSES_QUERY;
-                             case GeoArea.DISJOINT:
-                               // They do not overlap at all
-                               //System.out.println("    outside");
-                               return Relation.CELL_OUTSIDE_QUERY;
-                             default:
-                               assert false;
-                               return Relation.CELL_CROSSES_QUERY;
-                             }
-                           }
-                         });
-
-        return new ConstantScoreScorer(this, score(), result.build().iterator());
-      }
-    };
-  }
-
-  public String getField() {
-    return field;
-  }
-
-  public GeoShape getShape() {
-    return shape;
-  }
-
-  @Override
-  @SuppressWarnings({"unchecked","rawtypes"})
-  public boolean equals(Object o) {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
-    if (!super.equals(o)) return false;
-
-    PointInGeo3DShapeQuery that = (PointInGeo3DShapeQuery) o;
-
-    return shape.equals(that.shape);
-  }
-
-  @Override
-  public final int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + shape.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString(String field) {
-    final StringBuilder sb = new StringBuilder();
-    sb.append(getClass().getSimpleName());
-    sb.append(':');
-    if (this.field.equals(field) == false) {
-      sb.append(" field=");
-      sb.append(this.field);
-      sb.append(':');
-    }
-    sb.append(" Shape: ");
-    sb.append(shape);
-    return sb.toString();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/SidedPlane.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/SidedPlane.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/SidedPlane.java
deleted file mode 100755
index 7fc543d..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/SidedPlane.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Combination of a plane, and a sign value indicating what evaluation values are on the correct
- * side of the plane.
- *
- * @lucene.experimental
- */
-public class SidedPlane extends Plane implements Membership {
-  /** The sign value for evaluation of a point on the correct side of the plane */
-  public final double sigNum;
-
-  /**
-   * Construct a SidedPlane identical to an existing one, but reversed.
-   *
-   * @param sidedPlane is the existing plane.
-   */
-  public SidedPlane(SidedPlane sidedPlane) {
-    super(sidedPlane, sidedPlane.D);
-    this.sigNum = -sidedPlane.sigNum;
-  }
-
-  /**
-   * Construct a sided plane from a pair of vectors describing points, and including
-   * origin, plus a point p which describes the side.
-   *
-   * @param p point to evaluate
-   * @param A is the first in-plane point
-   * @param B is the second in-plane point
-   */
-  public SidedPlane(Vector p, Vector A, Vector B) {
-    super(A, B);
-    sigNum = Math.signum(evaluate(p));
-    if (sigNum == 0.0)
-      throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
-  }
-
-  /**
-   * Construct a sided plane from a point and a Z coordinate.
-   *
-   * @param p      point to evaluate.
-   * @param planetModel is the planet model.
-   * @param sinLat is the sin of the latitude of the plane.
-   */
-  public SidedPlane(Vector p, final PlanetModel planetModel, double sinLat) {
-    super(planetModel, sinLat);
-    sigNum = Math.signum(evaluate(p));
-    if (sigNum == 0.0)
-      throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
-  }
-
-  /**
-   * Construct a sided vertical plane from a point and specified x and y coordinates.
-   *
-   * @param p point to evaluate.
-   * @param x is the specified x.
-   * @param y is the specified y.
-   */
-  public SidedPlane(Vector p, double x, double y) {
-    super(x, y);
-    sigNum = Math.signum(evaluate(p));
-    if (sigNum == 0.0)
-      throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
-  }
-
-  /**
-   * Construct a sided plane with a normal vector and offset.
-   *
-   * @param p point to evaluate.
-   * @param v is the normal vector.
-   * @param D is the origin offset for the plan.
-   */
-  public SidedPlane(Vector p, Vector v, double D) {
-    super(v, D);
-    sigNum = Math.signum(evaluate(p));
-    if (sigNum == 0.0)
-      throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
-  }
-
-  /**
-   * Construct a sided plane with a normal vector and offset.
-   *
-   * @param pX X coord of point to evaluate.
-   * @param pY Y coord of point to evaluate.
-   * @param pZ Z coord of point to evaluate.
-   * @param v is the normal vector.
-   * @param D is the origin offset for the plan.
-   */
-  public SidedPlane(double pX, double pY, double pZ, Vector v, double D) {
-    super(v, D);
-    sigNum = Math.signum(evaluate(pX,pY,pZ));
-    if (sigNum == 0.0)
-      throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
-  }
-
-  /** Construct a sided plane from two points and a third normal vector.
-   */
-  public static SidedPlane constructNormalizedPerpendicularSidedPlane(final Vector insidePoint,
-    final Vector normalVector, final Vector point1, final Vector point2) {
-    final Vector pointsVector = new Vector(point1.x - point2.x, point1.y - point2.y, point1.z - point2.z);
-    final Vector newNormalVector = new Vector(normalVector, pointsVector);
-    try {
-      // To construct the plane, we now just need D, which is simply the negative of the evaluation of the circle normal vector at one of the points.
-      return new SidedPlane(insidePoint, newNormalVector, -newNormalVector.dotProduct(point1));
-    } catch (IllegalArgumentException e) {
-      return null;
-    }
-  }
-  
-  /** Construct a sided plane from three points.
-   */
-  public static SidedPlane constructNormalizedThreePointSidedPlane(final Vector insidePoint,
-    final Vector point1, final Vector point2, final Vector point3) {
-    try {
-      final Vector planeNormal = new Vector(
-        new Vector(point1.x - point2.x, point1.y - point2.y, point1.z - point2.z),
-        new Vector(point2.x - point3.x, point2.y - point3.y, point2.z - point3.z));
-      return new SidedPlane(insidePoint, planeNormal, -planeNormal.dotProduct(point2));
-    } catch (IllegalArgumentException e) {
-      return null;
-    }
-  }
-
-  @Override
-  public boolean isWithin(double x, double y, double z) {
-    double evalResult = evaluate(x, y, z);
-    if (Math.abs(evalResult) < MINIMUM_RESOLUTION)
-      return true;
-    double sigNum = Math.signum(evalResult);
-    return sigNum == this.sigNum;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) return true;
-    if (!(o instanceof SidedPlane)) return false;
-    if (!super.equals(o)) return false;
-
-    SidedPlane that = (SidedPlane) o;
-
-    return Double.compare(that.sigNum, sigNum) == 0;
-
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    long temp;
-    temp = Double.doubleToLongBits(sigNum);
-    result = 31 * result + (int) (temp ^ (temp >>> 32));
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "[A=" + x + ", B=" + y + ", C=" + z + ", D=" + D + ", side=" + sigNum + "]";
-  }
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/StandardXYZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/StandardXYZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/StandardXYZSolid.java
deleted file mode 100644
index cd54225..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/StandardXYZSolid.java
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * 3D rectangle, bounded on six sides by X,Y,Z limits
- *
- * @lucene.internal
- */
-public class StandardXYZSolid extends BaseXYZSolid {
-
-  /** Whole world? */
-  protected final boolean isWholeWorld;
-  /** Min-X plane */
-  protected final SidedPlane minXPlane;
-  /** Max-X plane */
-  protected final SidedPlane maxXPlane;
-  /** Min-Y plane */
-  protected final SidedPlane minYPlane;
-  /** Max-Y plane */
-  protected final SidedPlane maxYPlane;
-  /** Min-Z plane */
-  protected final SidedPlane minZPlane;
-  /** Max-Z plane */
-  protected final SidedPlane maxZPlane;
-  
-  /** These are the edge points of the shape, which are defined to be at least one point on
-   * each surface area boundary.  In the case of a solid, this includes points which represent
-   * the intersection of XYZ bounding planes and the planet, as well as points representing
-   * the intersection of single bounding planes with the planet itself.
-   */
-  protected final GeoPoint[] edgePoints;
-
-  /** Notable points for minXPlane */
-  protected final GeoPoint[] notableMinXPoints;
-  /** Notable points for maxXPlane */
-  protected final GeoPoint[] notableMaxXPoints;
-  /** Notable points for minYPlane */
-  protected final GeoPoint[] notableMinYPoints;
-  /** Notable points for maxYPlane */
-  protected final GeoPoint[] notableMaxYPoints;
-  /** Notable points for minZPlane */
-  protected final GeoPoint[] notableMinZPoints;
-  /** Notable points for maxZPlane */
-  protected final GeoPoint[] notableMaxZPoints;
-
-  /**
-   * Sole constructor
-   *
-   *@param planetModel is the planet model.
-   *@param minX is the minimum X value.
-   *@param maxX is the maximum X value.
-   *@param minY is the minimum Y value.
-   *@param maxY is the maximum Y value.
-   *@param minZ is the minimum Z value.
-   *@param maxZ is the maximum Z value.
-   */
-  public StandardXYZSolid(final PlanetModel planetModel,
-    final double minX,
-    final double maxX,
-    final double minY,
-    final double maxY,
-    final double minZ,
-    final double maxZ) {
-    super(planetModel);
-    // Argument checking
-    if (maxX - minX < Vector.MINIMUM_RESOLUTION)
-      throw new IllegalArgumentException("X values in wrong order or identical");
-    if (maxY - minY < Vector.MINIMUM_RESOLUTION)
-      throw new IllegalArgumentException("Y values in wrong order or identical");
-    if (maxZ - minZ < Vector.MINIMUM_RESOLUTION)
-      throw new IllegalArgumentException("Z values in wrong order or identical");
-
-    final double worldMinX = planetModel.getMinimumXValue();
-    final double worldMaxX = planetModel.getMaximumXValue();
-    final double worldMinY = planetModel.getMinimumYValue();
-    final double worldMaxY = planetModel.getMaximumYValue();
-    final double worldMinZ = planetModel.getMinimumZValue();
-    final double worldMaxZ = planetModel.getMaximumZValue();
-    
-    // We must distinguish between the case where the solid represents the entire world,
-    // and when the solid has no overlap with any part of the surface.  In both cases,
-    // there will be no edgepoints.
-    isWholeWorld =
-        (minX - worldMinX < -Vector.MINIMUM_RESOLUTION) &&
-        (maxX - worldMaxX > Vector.MINIMUM_RESOLUTION) &&
-        (minY - worldMinY < -Vector.MINIMUM_RESOLUTION) &&
-        (maxY - worldMaxY > Vector.MINIMUM_RESOLUTION) &&
-        (minZ - worldMinZ < -Vector.MINIMUM_RESOLUTION) &&
-        (maxZ - worldMaxZ > Vector.MINIMUM_RESOLUTION);
-
-    if (isWholeWorld) {
-      minXPlane = null;
-      maxXPlane = null;
-      minYPlane = null;
-      maxYPlane = null;
-      minZPlane = null;
-      maxZPlane = null;
-      notableMinXPoints = null;
-      notableMaxXPoints = null;
-      notableMinYPoints = null;
-      notableMaxYPoints = null;
-      notableMinZPoints = null;
-      notableMaxZPoints = null;
-      edgePoints = null;
-    } else {
-      // Construct the planes
-      minXPlane = new SidedPlane(maxX,0.0,0.0,xUnitVector,-minX);
-      maxXPlane = new SidedPlane(minX,0.0,0.0,xUnitVector,-maxX);
-      minYPlane = new SidedPlane(0.0,maxY,0.0,yUnitVector,-minY);
-      maxYPlane = new SidedPlane(0.0,minY,0.0,yUnitVector,-maxY);
-      minZPlane = new SidedPlane(0.0,0.0,maxZ,zUnitVector,-minZ);
-      maxZPlane = new SidedPlane(0.0,0.0,minZ,zUnitVector,-maxZ);
-      
-      // We need at least one point on the planet surface for each manifestation of the shape.
-      // There can be up to 2 (on opposite sides of the world).  But we have to go through
-      // 12 combinations of adjacent planes in order to find out if any have 2 intersection solution.
-      // Typically, this requires 12 square root operations. 
-      final GeoPoint[] minXminY = minXPlane.findIntersections(planetModel,minYPlane,maxXPlane,maxYPlane,minZPlane,maxZPlane);
-      final GeoPoint[] minXmaxY = minXPlane.findIntersections(planetModel,maxYPlane,maxXPlane,minYPlane,minZPlane,maxZPlane);
-      final GeoPoint[] minXminZ = minXPlane.findIntersections(planetModel,minZPlane,maxXPlane,maxZPlane,minYPlane,maxYPlane);
-      final GeoPoint[] minXmaxZ = minXPlane.findIntersections(planetModel,maxZPlane,maxXPlane,minZPlane,minYPlane,maxYPlane);
-
-      final GeoPoint[] maxXminY = maxXPlane.findIntersections(planetModel,minYPlane,minXPlane,maxYPlane,minZPlane,maxZPlane);
-      final GeoPoint[] maxXmaxY = maxXPlane.findIntersections(planetModel,maxYPlane,minXPlane,minYPlane,minZPlane,maxZPlane);
-      final GeoPoint[] maxXminZ = maxXPlane.findIntersections(planetModel,minZPlane,minXPlane,maxZPlane,minYPlane,maxYPlane);
-      final GeoPoint[] maxXmaxZ = maxXPlane.findIntersections(planetModel,maxZPlane,minXPlane,minZPlane,minYPlane,maxYPlane);
-      
-      final GeoPoint[] minYminZ = minYPlane.findIntersections(planetModel,minZPlane,maxYPlane,maxZPlane,minXPlane,maxXPlane);
-      final GeoPoint[] minYmaxZ = minYPlane.findIntersections(planetModel,maxZPlane,maxYPlane,minZPlane,minXPlane,maxXPlane);
-      final GeoPoint[] maxYminZ = maxYPlane.findIntersections(planetModel,minZPlane,minYPlane,maxZPlane,minXPlane,maxXPlane);
-      final GeoPoint[] maxYmaxZ = maxYPlane.findIntersections(planetModel,maxZPlane,minYPlane,minZPlane,minXPlane,maxXPlane);
-      
-      notableMinXPoints = glueTogether(minXminY, minXmaxY, minXminZ, minXmaxZ);
-      notableMaxXPoints = glueTogether(maxXminY, maxXmaxY, maxXminZ, maxXmaxZ);
-      notableMinYPoints = glueTogether(minXminY, maxXminY, minYminZ, minYmaxZ);
-      notableMaxYPoints = glueTogether(minXmaxY, maxXmaxY, maxYminZ, maxYmaxZ);
-      notableMinZPoints = glueTogether(minXminZ, maxXminZ, minYminZ, maxYminZ);
-      notableMaxZPoints = glueTogether(minXmaxZ, maxXmaxZ, minYmaxZ, maxYmaxZ);
-
-      // Now, compute the edge points.
-      // This is the trickiest part of setting up an XYZSolid.  We've computed intersections already, so
-      // we'll start there.
-      // There can be a number of shapes, each of which needs an edgepoint.  Each side by itself might contribute
-      // an edgepoint, for instance, if the plane describing that side intercepts the planet in such a way that the ellipse
-      // of interception does not meet any other planes.  Plane intersections can each contribute 0, 1, or 2 edgepoints.
-      //
-      // All of this makes for a lot of potential edgepoints, but I believe these can be pruned back with careful analysis.
-      // I haven't yet done that analysis, however, so I will treat them all as individual edgepoints.
-      
-      // The cases we are looking for are when the four corner points for any given
-      // plane are all outside of the world, AND that plane intersects the world.
-      // There are eight corner points all told; we must evaluate these WRT the planet surface.
-      final boolean minXminYminZ = planetModel.pointOutside(minX, minY, minZ);
-      final boolean minXminYmaxZ = planetModel.pointOutside(minX, minY, maxZ);
-      final boolean minXmaxYminZ = planetModel.pointOutside(minX, maxY, minZ);
-      final boolean minXmaxYmaxZ = planetModel.pointOutside(minX, maxY, maxZ);
-      final boolean maxXminYminZ = planetModel.pointOutside(maxX, minY, minZ);
-      final boolean maxXminYmaxZ = planetModel.pointOutside(maxX, minY, maxZ);
-      final boolean maxXmaxYminZ = planetModel.pointOutside(maxX, maxY, minZ);
-      final boolean maxXmaxYmaxZ = planetModel.pointOutside(maxX, maxY, maxZ);
-        
-      // Look at single-plane/world intersections.
-      // We detect these by looking at the world model and noting its x, y, and z bounds.
-
-      final GeoPoint[] minXEdges;
-      if (minX - worldMinX >= -Vector.MINIMUM_RESOLUTION && minX - worldMaxX <= Vector.MINIMUM_RESOLUTION &&
-        minY < 0.0 && maxY > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
-        minXminYminZ && minXminYmaxZ && minXmaxYminZ && minXmaxYmaxZ) {
-        // Find any point on the minX plane that intersects the world
-        // First construct a perpendicular plane that will allow us to find a sample point.
-        // This plane is vertical and goes through the points (0,0,0) and (1,0,0)
-        // Then use it to compute a sample point.
-        final GeoPoint intPoint = minXPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
-        if (intPoint != null) {
-          minXEdges = new GeoPoint[]{intPoint};
-        } else {
-          // No intersection found?
-          minXEdges = EMPTY_POINTS;
-        }
-      } else {
-        minXEdges = EMPTY_POINTS;
-      }
-      
-      final GeoPoint[] maxXEdges;
-      if (maxX - worldMinX >= -Vector.MINIMUM_RESOLUTION && maxX - worldMaxX <= Vector.MINIMUM_RESOLUTION &&
-        minY < 0.0 && maxY > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
-        maxXminYminZ && maxXminYmaxZ && maxXmaxYminZ && maxXmaxYmaxZ) {
-        // Find any point on the maxX plane that intersects the world
-        // First construct a perpendicular plane that will allow us to find a sample point.
-        // This plane is vertical and goes through the points (0,0,0) and (1,0,0)
-        // Then use it to compute a sample point.
-        final GeoPoint intPoint = maxXPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
-        if (intPoint != null) {
-          maxXEdges = new GeoPoint[]{intPoint};
-        } else {
-          maxXEdges = EMPTY_POINTS;
-        }
-      } else {
-        maxXEdges = EMPTY_POINTS;
-      }
-      
-      final GeoPoint[] minYEdges;
-      if (minY - worldMinY >= -Vector.MINIMUM_RESOLUTION && minY - worldMaxY <= Vector.MINIMUM_RESOLUTION &&
-        minX < 0.0 && maxX > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
-        minXminYminZ && minXminYmaxZ && maxXminYminZ && maxXminYmaxZ) {
-        // Find any point on the minY plane that intersects the world
-        // First construct a perpendicular plane that will allow us to find a sample point.
-        // This plane is vertical and goes through the points (0,0,0) and (0,1,0)
-        // Then use it to compute a sample point.
-        final GeoPoint intPoint = minYPlane.getSampleIntersectionPoint(planetModel, yVerticalPlane);
-        if (intPoint != null) {
-          minYEdges = new GeoPoint[]{intPoint};
-        } else {
-          minYEdges = EMPTY_POINTS;
-        }
-      } else {
-        minYEdges = EMPTY_POINTS;
-      }
-      
-      final GeoPoint[] maxYEdges;
-      if (maxY - worldMinY >= -Vector.MINIMUM_RESOLUTION && maxY - worldMaxY <= Vector.MINIMUM_RESOLUTION &&
-        minX < 0.0 && maxX > 0.0 && minZ < 0.0 && maxZ > 0.0 &&
-        minXmaxYminZ && minXmaxYmaxZ && maxXmaxYminZ && maxXmaxYmaxZ) {
-        // Find any point on the maxY plane that intersects the world
-        // First construct a perpendicular plane that will allow us to find a sample point.
-        // This plane is vertical and goes through the points (0,0,0) and (0,1,0)
-        // Then use it to compute a sample point.
-        final GeoPoint intPoint = maxYPlane.getSampleIntersectionPoint(planetModel, yVerticalPlane);
-        if (intPoint != null) {
-          maxYEdges = new GeoPoint[]{intPoint};
-        } else {
-          maxYEdges = EMPTY_POINTS;
-        }
-      } else {
-        maxYEdges = EMPTY_POINTS;
-      }
-      
-      final GeoPoint[] minZEdges;
-      if (minZ - worldMinZ >= -Vector.MINIMUM_RESOLUTION && minZ - worldMaxZ <= Vector.MINIMUM_RESOLUTION &&
-        minX < 0.0 && maxX > 0.0 && minY < 0.0 && maxY > 0.0 &&
-        minXminYminZ && minXmaxYminZ && maxXminYminZ && maxXmaxYminZ) {
-        // Find any point on the minZ plane that intersects the world
-        // First construct a perpendicular plane that will allow us to find a sample point.
-        // This plane is vertical and goes through the points (0,0,0) and (1,0,0)
-        // Then use it to compute a sample point.
-        final GeoPoint intPoint = minZPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
-        if (intPoint != null) {
-          minZEdges = new GeoPoint[]{intPoint};
-        } else {
-          minZEdges = EMPTY_POINTS;
-        }
-      } else {
-        minZEdges = EMPTY_POINTS;
-      }
-      
-      final GeoPoint[] maxZEdges;
-      if (maxZ - worldMinZ >= -Vector.MINIMUM_RESOLUTION && maxZ - worldMaxZ <= Vector.MINIMUM_RESOLUTION &&
-        minX < 0.0 && maxX > 0.0 && minY < 0.0 && maxY > 0.0 &&
-        minXminYmaxZ && minXmaxYmaxZ && maxXminYmaxZ && maxXmaxYmaxZ) {
-        // Find any point on the maxZ plane that intersects the world
-        // First construct a perpendicular plane that will allow us to find a sample point.
-        // This plane is vertical and goes through the points (0,0,0) and (1,0,0) (that is, its orientation doesn't matter)
-        // Then use it to compute a sample point.
-        final GeoPoint intPoint = maxZPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
-        if (intPoint != null) {
-          maxZEdges = new GeoPoint[]{intPoint};
-        } else {
-          maxZEdges = EMPTY_POINTS;
-        }
-      } else {
-        maxZEdges = EMPTY_POINTS;
-      }
-      
-      // Glue everything together.  This is not a minimal set of edgepoints, as of now, but it does completely describe all shapes on the
-      // planet.
-      this.edgePoints = glueTogether(minXminY, minXmaxY, minXminZ, minXmaxZ,
-        maxXminY, maxXmaxY, maxXminZ, maxXmaxZ,
-        minYminZ, minYmaxZ, maxYminZ, maxYmaxZ,
-        minXEdges, maxXEdges, minYEdges, maxYEdges, minZEdges, maxZEdges);
-    }
-  }
-
-  @Override
-  protected GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-  
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    if (isWholeWorld) {
-      return true;
-    }
-    return minXPlane.isWithin(x, y, z) &&
-      maxXPlane.isWithin(x, y, z) &&
-      minYPlane.isWithin(x, y, z) &&
-      maxYPlane.isWithin(x, y, z) &&
-      minZPlane.isWithin(x, y, z) &&
-      maxZPlane.isWithin(x, y, z);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    if (isWholeWorld) {
-      if (path.getEdgePoints().length > 0)
-        return WITHIN;
-      return OVERLAPS;
-    }
-    
-    /*
-    for (GeoPoint p : getEdgePoints()) {
-      System.err.println(" Edge point "+p+" path.isWithin()? "+path.isWithin(p));
-    }
-    
-    for (GeoPoint p : path.getEdgePoints()) {
-      System.err.println(" path edge point "+p+" isWithin()? "+isWithin(p)+" minx="+minXPlane.evaluate(p)+" maxx="+maxXPlane.evaluate(p)+" miny="+minYPlane.evaluate(p)+" maxy="+maxYPlane.evaluate(p)+" minz="+minZPlane.evaluate(p)+" maxz="+maxZPlane.evaluate(p));
-    }
-    */
-    
-    //System.err.println(this+" getrelationship with "+path);
-    final int insideRectangle = isShapeInsideArea(path);
-    if (insideRectangle == SOME_INSIDE) {
-      //System.err.println(" some shape points inside area");
-      return OVERLAPS;
-    }
-
-    // Figure out if the entire XYZArea is contained by the shape.
-    final int insideShape = isAreaInsideShape(path);
-    if (insideShape == SOME_INSIDE) {
-      //System.err.println(" some area points inside shape");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
-      //System.err.println(" inside of each other");
-      return OVERLAPS;
-    }
-
-    if (path.intersects(minXPlane, notableMinXPoints, maxXPlane, minYPlane, maxYPlane, minZPlane, maxZPlane) ||
-        path.intersects(maxXPlane, notableMaxXPoints, minXPlane, minYPlane, maxYPlane, minZPlane, maxZPlane) ||
-        path.intersects(minYPlane, notableMinYPoints, maxYPlane, minXPlane, maxXPlane, minZPlane, maxZPlane) ||
-        path.intersects(maxYPlane, notableMaxYPoints, minYPlane, minXPlane, maxXPlane, minZPlane, maxZPlane) ||
-        path.intersects(minZPlane, notableMinZPoints, maxZPlane, minXPlane, maxXPlane, minYPlane, maxYPlane) ||
-        path.intersects(maxZPlane, notableMaxZPoints, minZPlane, minXPlane, maxXPlane, minYPlane, maxYPlane)) {
-      //System.err.println(" edges intersect");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE) {
-      //System.err.println(" all shape points inside area");
-      return WITHIN;
-    }
-
-    if (insideShape == ALL_INSIDE) {
-      //System.err.println(" all area points inside shape");
-      return CONTAINS;
-    }
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof StandardXYZSolid))
-      return false;
-    StandardXYZSolid other = (StandardXYZSolid) o;
-    if (!super.equals(other) ||
-      other.isWholeWorld != isWholeWorld) {
-      return false;
-    }
-    if (!isWholeWorld) {
-      return other.minXPlane.equals(minXPlane) &&
-        other.maxXPlane.equals(maxXPlane) &&
-        other.minYPlane.equals(minYPlane) &&
-        other.maxYPlane.equals(maxYPlane) &&
-        other.minZPlane.equals(minZPlane) &&
-        other.maxZPlane.equals(maxZPlane);
-    }
-    return true;
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result + (isWholeWorld?1:0);
-    if (!isWholeWorld) {
-      result = 31 * result  + minXPlane.hashCode();
-      result = 31 * result  + maxXPlane.hashCode();
-      result = 31 * result  + minYPlane.hashCode();
-      result = 31 * result  + maxYPlane.hashCode();
-      result = 31 * result  + minZPlane.hashCode();
-      result = 31 * result  + maxZPlane.hashCode();
-    }
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "StandardXYZSolid: {planetmodel="+planetModel+", isWholeWorld="+isWholeWorld+", minXplane="+minXPlane+", maxXplane="+maxXPlane+", minYplane="+minYPlane+", maxYplane="+maxYPlane+", minZplane="+minZPlane+", maxZplane="+maxZPlane+"}";
-  }
-  
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Tools.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Tools.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Tools.java
deleted file mode 100755
index 89d37aa..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Tools.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Static methods globally useful for 3d geometric work.
- *
- * @lucene.experimental
- */
-public class Tools {
-  private Tools() {
-  }
-
-  /**
-   * Java acos yields a NAN if you take an arc-cos of an
-   * angle that's just a tiny bit greater than 1.0, so
-   * here's a more resilient version.
-   */
-  public static double safeAcos(double value) {
-    if (value > 1.0)
-      value = 1.0;
-    else if (value < -1.0)
-      value = -1.0;
-    return Math.acos(value);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Vector.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Vector.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Vector.java
deleted file mode 100755
index 1a3972d..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Vector.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * A 3d vector in space, not necessarily
- * going through the origin.
- *
- * @lucene.experimental
- */
-public class Vector {
-  /**
-   * Values that are all considered to be essentially zero have a magnitude
-   * less than this.
-   */
-  public static final double MINIMUM_RESOLUTION = 1.0e-12;
-  /**
-   * For squared quantities, the bound is squared too.
-   */
-  public static final double MINIMUM_RESOLUTION_SQUARED = MINIMUM_RESOLUTION * MINIMUM_RESOLUTION;
-  /**
-   * For cubed quantities, cube the bound.
-   */
-  public static final double MINIMUM_RESOLUTION_CUBED = MINIMUM_RESOLUTION_SQUARED * MINIMUM_RESOLUTION;
-
-  /** The x value */
-  public final double x;
-  /** The y value */
-  public final double y;
-  /** The z value */
-  public final double z;
-
-  /**
-   * Construct from (U.S.) x,y,z coordinates.
-   *@param x is the x value.
-   *@param y is the y value.
-   *@param z is the z value.
-   */
-  public Vector(double x, double y, double z) {
-    this.x = x;
-    this.y = y;
-    this.z = z;
-  }
-
-  /**
-   * Construct a vector that is perpendicular to
-   * two other (non-zero) vectors.  If the vectors are parallel,
-   * IllegalArgumentException will be thrown.
-   * Produces a normalized final vector.
-   *
-   * @param A is the first vector
-   * @param B is the second
-   */
-  public Vector(final Vector A, final Vector B) {
-    // x = u2v3 - u3v2
-    // y = u3v1 - u1v3
-    // z = u1v2 - u2v1
-    final double thisX = A.y * B.z - A.z * B.y;
-    final double thisY = A.z * B.x - A.x * B.z;
-    final double thisZ = A.x * B.y - A.y * B.x;
-    final double magnitude = magnitude(thisX, thisY, thisZ);
-    if (Math.abs(magnitude) < MINIMUM_RESOLUTION) {
-      throw new IllegalArgumentException("Degenerate/parallel vector constructed");
-    }
-    final double inverseMagnitude = 1.0 / magnitude;
-    this.x = thisX * inverseMagnitude;
-    this.y = thisY * inverseMagnitude;
-    this.z = thisZ * inverseMagnitude;
-  }
-
-  /** Compute a magnitude of an x,y,z value.
-   */
-  public static double magnitude(final double x, final double y, final double z) {
-    return Math.sqrt(x*x + y*y + z*z);
-  }
-  
-  /**
-   * Compute a normalized unit vector based on the current vector.
-   *
-   * @return the normalized vector, or null if the current vector has
-   * a magnitude of zero.
-   */
-  public Vector normalize() {
-    double denom = magnitude();
-    if (denom < MINIMUM_RESOLUTION)
-      // Degenerate, can't normalize
-      return null;
-    double normFactor = 1.0 / denom;
-    return new Vector(x * normFactor, y * normFactor, z * normFactor);
-  }
-
-  /**
-   * Do a dot product.
-   *
-   * @param v is the vector to multiply.
-   * @return the result.
-   */
-  public double dotProduct(final Vector v) {
-    return this.x * v.x + this.y * v.y + this.z * v.z;
-  }
-
-  /**
-   * Do a dot product.
-   *
-   * @param x is the x value of the vector to multiply.
-   * @param y is the y value of the vector to multiply.
-   * @param z is the z value of the vector to multiply.
-   * @return the result.
-   */
-  public double dotProduct(final double x, final double y, final double z) {
-    return this.x * x + this.y * y + this.z * z;
-  }
-
-  /**
-   * Determine if this vector, taken from the origin,
-   * describes a point within a set of planes.
-   *
-   * @param bounds     is the first part of the set of planes.
-   * @param moreBounds is the second part of the set of planes.
-   * @return true if the point is within the bounds.
-   */
-  public boolean isWithin(final Membership[] bounds, final Membership[] moreBounds) {
-    // Return true if the point described is within all provided bounds
-    //System.err.println("  checking if "+this+" is within bounds");
-    for (Membership bound : bounds) {
-      if (bound != null && !bound.isWithin(this)) {
-        //System.err.println("    NOT within "+bound);
-        return false;
-      }
-    }
-    for (Membership bound : moreBounds) {
-      if (bound != null && !bound.isWithin(this)) {
-        //System.err.println("    NOT within "+bound);
-        return false;
-      }
-    }
-    //System.err.println("    is within");
-    return true;
-  }
-
-  /**
-   * Translate vector.
-   */
-  public Vector translate(final double xOffset, final double yOffset, final double zOffset) {
-    return new Vector(x - xOffset, y - yOffset, z - zOffset);
-  }
-
-  /**
-   * Rotate vector counter-clockwise in x-y by an angle.
-   */
-  public Vector rotateXY(final double angle) {
-    return rotateXY(Math.sin(angle), Math.cos(angle));
-  }
-
-  /**
-   * Rotate vector counter-clockwise in x-y by an angle, expressed as sin and cos.
-   */
-  public Vector rotateXY(final double sinAngle, final double cosAngle) {
-    return new Vector(x * cosAngle - y * sinAngle, x * sinAngle + y * cosAngle, z);
-  }
-
-  /**
-   * Rotate vector counter-clockwise in x-z by an angle.
-   */
-  public Vector rotateXZ(final double angle) {
-    return rotateXZ(Math.sin(angle), Math.cos(angle));
-  }
-
-  /**
-   * Rotate vector counter-clockwise in x-z by an angle, expressed as sin and cos.
-   */
-  public Vector rotateXZ(final double sinAngle, final double cosAngle) {
-    return new Vector(x * cosAngle - z * sinAngle, y, x * sinAngle + z * cosAngle);
-  }
-
-  /**
-   * Rotate vector counter-clockwise in z-y by an angle.
-   */
-  public Vector rotateZY(final double angle) {
-    return rotateZY(Math.sin(angle), Math.cos(angle));
-  }
-
-  /**
-   * Rotate vector counter-clockwise in z-y by an angle, expressed as sin and cos.
-   */
-  public Vector rotateZY(final double sinAngle, final double cosAngle) {
-    return new Vector(x, z * sinAngle + y * cosAngle, z * cosAngle - y * sinAngle);
-  }
-
-  /**
-   * Compute the square of a straight-line distance to a point described by the
-   * vector taken from the origin.
-   * Monotonically increasing for arc distances up to PI.
-   *
-   * @param v is the vector to compute a distance to.
-   * @return the square of the linear distance.
-   */
-  public double linearDistanceSquared(final Vector v) {
-    double deltaX = this.x - v.x;
-    double deltaY = this.y - v.y;
-    double deltaZ = this.z - v.z;
-    return deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
-  }
-
-  /**
-   * Compute the square of a straight-line distance to a point described by the
-   * vector taken from the origin.
-   * Monotonically increasing for arc distances up to PI.
-   *
-   * @param x is the x part of the vector to compute a distance to.
-   * @param y is the y part of the vector to compute a distance to.
-   * @param z is the z part of the vector to compute a distance to.
-   * @return the square of the linear distance.
-   */
-  public double linearDistanceSquared(final double x, final double y, final double z) {
-    double deltaX = this.x - x;
-    double deltaY = this.y - y;
-    double deltaZ = this.z - z;
-    return deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
-  }
-
-  /**
-   * Compute the straight-line distance to a point described by the
-   * vector taken from the origin.
-   * Monotonically increasing for arc distances up to PI.
-   *
-   * @param v is the vector to compute a distance to.
-   * @return the linear distance.
-   */
-  public double linearDistance(final Vector v) {
-    return Math.sqrt(linearDistanceSquared(v));
-  }
-
-  /**
-   * Compute the straight-line distance to a point described by the
-   * vector taken from the origin.
-   * Monotonically increasing for arc distances up to PI.
-   *
-   * @param x is the x part of the vector to compute a distance to.
-   * @param y is the y part of the vector to compute a distance to.
-   * @param z is the z part of the vector to compute a distance to.
-   * @return the linear distance.
-   */
-  public double linearDistance(final double x, final double y, final double z) {
-    return Math.sqrt(linearDistanceSquared(x, y, z));
-  }
-
-  /**
-   * Compute the square of the normal distance to a vector described by a
-   * vector taken from the origin.
-   * Monotonically increasing for arc distances up to PI/2.
-   *
-   * @param v is the vector to compute a distance to.
-   * @return the square of the normal distance.
-   */
-  public double normalDistanceSquared(final Vector v) {
-    double t = dotProduct(v);
-    double deltaX = this.x * t - v.x;
-    double deltaY = this.y * t - v.y;
-    double deltaZ = this.z * t - v.z;
-    return deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
-  }
-
-  /**
-   * Compute the square of the normal distance to a vector described by a
-   * vector taken from the origin.
-   * Monotonically increasing for arc distances up to PI/2.
-   *
-   * @param x is the x part of the vector to compute a distance to.
-   * @param y is the y part of the vector to compute a distance to.
-   * @param z is the z part of the vector to compute a distance to.
-   * @return the square of the normal distance.
-   */
-  public double normalDistanceSquared(final double x, final double y, final double z) {
-    double t = dotProduct(x, y, z);
-    double deltaX = this.x * t - x;
-    double deltaY = this.y * t - y;
-    double deltaZ = this.z * t - z;
-    return deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;
-  }
-
-  /**
-   * Compute the normal (perpendicular) distance to a vector described by a
-   * vector taken from the origin.
-   * Monotonically increasing for arc distances up to PI/2.
-   *
-   * @param v is the vector to compute a distance to.
-   * @return the normal distance.
-   */
-  public double normalDistance(final Vector v) {
-    return Math.sqrt(normalDistanceSquared(v));
-  }
-
-  /**
-   * Compute the normal (perpendicular) distance to a vector described by a
-   * vector taken from the origin.
-   * Monotonically increasing for arc distances up to PI/2.
-   *
-   * @param x is the x part of the vector to compute a distance to.
-   * @param y is the y part of the vector to compute a distance to.
-   * @param z is the z part of the vector to compute a distance to.
-   * @return the normal distance.
-   */
-  public double normalDistance(final double x, final double y, final double z) {
-    return Math.sqrt(normalDistanceSquared(x, y, z));
-  }
-
-  /**
-   * Compute the magnitude of this vector.
-   *
-   * @return the magnitude.
-   */
-  public double magnitude() {
-    return magnitude(x,y,z);
-  }
-
-  /** Compute the desired magnitude of a unit vector projected to a given
-   * planet model.
-   * @param planetModel is the planet model.
-   * @param x is the unit vector x value.
-   * @param y is the unit vector y value.
-   * @param z is the unit vector z value.
-   * @return a magnitude value for that (x,y,z) that projects the vector onto the specified ellipsoid.
-   */
-  protected static double computeDesiredEllipsoidMagnitude(final PlanetModel planetModel, final double x, final double y, final double z) {
-    return 1.0 / Math.sqrt(x*x*planetModel.inverseAbSquared + y*y*planetModel.inverseAbSquared + z*z*planetModel.inverseCSquared);
-  }
-
-  /** Compute the desired magnitude of a unit vector projected to a given
-   * planet model.  The unit vector is specified only by a z value.
-   * @param planetModel is the planet model.
-   * @param z is the unit vector z value.
-   * @return a magnitude value for that z value that projects the vector onto the specified ellipsoid.
-   */
-  protected static double computeDesiredEllipsoidMagnitude(final PlanetModel planetModel, final double z) {
-    return 1.0 / Math.sqrt((1.0-z*z)*planetModel.inverseAbSquared + z*z*planetModel.inverseCSquared);
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof Vector))
-      return false;
-    Vector other = (Vector) o;
-    return (other.x == x && other.y == y && other.z == z);
-  }
-
-  @Override
-  public int hashCode() {
-    int result;
-    long temp;
-    temp = Double.doubleToLongBits(x);
-    result = (int) (temp ^ (temp >>> 32));
-    temp = Double.doubleToLongBits(y);
-    result = 31 * result + (int) (temp ^ (temp >>> 32));
-    temp = Double.doubleToLongBits(z);
-    result = 31 * result + (int) (temp ^ (temp >>> 32));
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "[X=" + x + ", Y=" + y + ", Z=" + z + "]";
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZBounds.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZBounds.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZBounds.java
deleted file mode 100644
index 22e324b..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZBounds.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * An object for accumulating XYZ bounds information.
- *
- * @lucene.experimental
- */
-public class XYZBounds implements Bounds {
-
-  /** A 'fudge factor', which is added to maximums and subtracted from minimums,
-   * in order to compensate for potential error deltas.  This would not be necessary
-   * except that our 'bounds' is defined as always equaling or exceeding the boundary
-   * of the shape, and we cannot guarantee that without making MINIMUM_RESOLUTION
-   * unacceptably large.
-   */
-  protected static final double FUDGE_FACTOR = Vector.MINIMUM_RESOLUTION * 2.0;
-  
-  /** Minimum x */
-  protected Double minX = null;
-  /** Maximum x */
-  protected Double maxX = null;
-  /** Minimum y */
-  protected Double minY = null;
-  /** Maximum y */
-  protected Double maxY = null;
-  /** Minimum z */
-  protected Double minZ = null;
-  /** Maximum z */
-  protected Double maxZ = null;
-  
-  /** 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;
-
-  /** Construct an empty bounds object */
-  public XYZBounds() {
-  }
-
-  // Accessor methods
-  
-  /** Return the minimum X value.
-   *@return minimum X value.
-   */
-  public Double getMinimumX() {
-    return minX;
-  }
-
-  /** Return the maximum X value.
-   *@return maximum X value.
-   */
-  public Double getMaximumX() {
-    return maxX;
-  }
-
-  /** Return the minimum Y value.
-   *@return minimum Y value.
-   */
-  public Double getMinimumY() {
-    return minY;
-  }
-
-  /** Return the maximum Y value.
-   *@return maximum Y value.
-   */
-  public Double getMaximumY() {
-    return maxY;
-  }
-  
-  /** Return the minimum Z value.
-   *@return minimum Z value.
-   */
-  public Double getMinimumZ() {
-    return minZ;
-  }
-
-  /** Return the maximum Z value.
-   *@return maximum Z value.
-   */
-  public Double getMaximumZ() {
-    return maxZ;
-  }
-
-  /** Return true if minX is as small as the planet model allows.
-   *@return true if minX has reached its bound.
-   */
-  public boolean isSmallestMinX(final PlanetModel planetModel) {
-    if (minX == null)
-      return false;
-    return minX - planetModel.getMinimumXValue() < Vector.MINIMUM_RESOLUTION;
-  }
-  
-  /** Return true if maxX is as large as the planet model allows.
-   *@return true if maxX has reached its bound.
-   */
-  public boolean isLargestMaxX(final PlanetModel planetModel) {
-    if (maxX == null)
-      return false;
-    return planetModel.getMaximumXValue() - maxX < Vector.MINIMUM_RESOLUTION;
-  }
-
-  /** Return true if minY is as small as the planet model allows.
-   *@return true if minY has reached its bound.
-   */
-  public boolean isSmallestMinY(final PlanetModel planetModel) {
-    if (minY == null)
-      return false;
-    return minY - planetModel.getMinimumYValue() < Vector.MINIMUM_RESOLUTION;
-  }
-  
-  /** Return true if maxY is as large as the planet model allows.
-   *@return true if maxY has reached its bound.
-   */
-  public boolean isLargestMaxY(final PlanetModel planetModel) {
-    if (maxY == null)
-      return false;
-    return planetModel.getMaximumYValue() - maxY < Vector.MINIMUM_RESOLUTION;
-  }
-  
-  /** Return true if minZ is as small as the planet model allows.
-   *@return true if minZ has reached its bound.
-   */
-  public boolean isSmallestMinZ(final PlanetModel planetModel) {
-    if (minZ == null)
-      return false;
-    return minZ - planetModel.getMinimumZValue() < Vector.MINIMUM_RESOLUTION;
-  }
-  
-  /** Return true if maxZ is as large as the planet model allows.
-   *@return true if maxZ has reached its bound.
-   */
-  public boolean isLargestMaxZ(final PlanetModel planetModel) {
-    if (maxZ == null)
-      return false;
-    return planetModel.getMaximumZValue() - maxZ < Vector.MINIMUM_RESOLUTION;
-  }
-
-  // Modification methods
-  
-  @Override
-  public Bounds addPlane(final PlanetModel planetModel, final Plane plane, final Membership... bounds) {
-    plane.recordBounds(planetModel, this, bounds);
-    return this;
-  }
-
-  /** 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.
-   *@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) {
-    return addPlane(planetModel, horizontalPlane, 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) {
-    return addPlane(planetModel, verticalPlane, bounds);
-  }
-
-  @Override
-  public Bounds addXValue(final GeoPoint point) {
-    final double x = point.x;
-    final double small = x - FUDGE_FACTOR;
-    if (minX == null || minX > small) {
-      minX = new Double(small);
-    }
-    final double large = x + FUDGE_FACTOR;
-    if (maxX == null || maxX < large) {
-      maxX = new Double(large);
-    }
-    return this;
-  }
-
-  @Override
-  public Bounds addYValue(final GeoPoint point) {
-    final double y = point.y;
-    final double small = y - FUDGE_FACTOR;
-    if (minY == null || minY > small) {
-      minY = new Double(small);
-    }
-    final double large = y + FUDGE_FACTOR;
-    if (maxY == null || maxY < large) {
-      maxY = new Double(large);
-    }
-    return this;
-  }
-
-  @Override
-  public Bounds addZValue(final GeoPoint point) {
-    final double z = point.z;
-    final double small = z - FUDGE_FACTOR;
-    if (minZ == null || minZ > small) {
-      minZ = new Double(small);
-    }
-    final double large = z + FUDGE_FACTOR;
-    if (maxZ == null || maxZ < large) {
-      maxZ = new Double(large);
-    }
-    return this;
-  }
-
-  @Override
-  public Bounds addPoint(final GeoPoint point) {
-    return addXValue(point).addYValue(point).addZValue(point);
-  }
-
-  @Override
-  public Bounds isWide() {
-    // No specific thing we need to do.
-    return this;
-  }
-
-  @Override
-  public Bounds noLongitudeBound() {
-    // No specific thing we need to do.
-    return this;
-  }
-
-  @Override
-  public Bounds noTopLatitudeBound() {
-    // No specific thing we need to do.
-    return this;
-  }
-
-  @Override
-  public Bounds noBottomLatitudeBound() {
-    // No specific thing we need to do.
-    return this;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZSolid.java
deleted file mode 100644
index ab46402..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZSolid.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Interface for a family of 3D rectangles, bounded on six sides by X,Y,Z limits
- *
- * @lucene.internal
- */
-public interface XYZSolid extends GeoArea {
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZSolidFactory.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZSolidFactory.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZSolidFactory.java
deleted file mode 100644
index 409ba86..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZSolidFactory.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Factory for {@link org.apache.lucene.geo3d.XYZSolid}.
- *
- * @lucene.experimental
- */
-public class XYZSolidFactory {
-  private XYZSolidFactory() {
-  }
-
-  /**
-   * Create a XYZSolid of the right kind given (x,y,z) bounds.
-   * @param planetModel is the planet model
-   * @param minX is the min X boundary
-   * @param maxX is the max X boundary
-   * @param minY is the min Y boundary
-   * @param maxY is the max Y boundary
-   * @param minZ is the min Z boundary
-   * @param maxZ is the max Z boundary
-   */
-  public static XYZSolid makeXYZSolid(final PlanetModel planetModel, final double minX, final double maxX, final double minY, final double maxY, final double minZ, final double maxZ) {
-    if (Math.abs(maxX - minX) < Vector.MINIMUM_RESOLUTION) {
-      if (Math.abs(maxY - minY) < Vector.MINIMUM_RESOLUTION) {
-        if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
-          return new dXdYdZSolid(planetModel, (minX+maxX) * 0.5, (minY+maxY) * 0.5, minZ);
-        } else {
-          return new dXdYZSolid(planetModel, (minX+maxX) * 0.5, (minY+maxY) * 0.5, minZ, maxZ);
-        }
-      } else {
-        if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
-          return new dXYdZSolid(planetModel, (minX+maxX) * 0.5, minY, maxY, (minZ+maxZ) * 0.5);
-        } else {
-          return new dXYZSolid(planetModel, (minX+maxX) * 0.5, minY, maxY, minZ, maxZ);
-        }
-      }
-    }
-    if (Math.abs(maxY - minY) < Vector.MINIMUM_RESOLUTION) {
-      if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
-        return new XdYdZSolid(planetModel, minX, maxX, (minY+maxY) * 0.5, (minZ+maxZ) * 0.5);
-      } else {
-        return new XdYZSolid(planetModel, minX, maxX, (minY+maxY) * 0.5, minZ, maxZ);
-      }
-    }
-    if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
-      return new XYdZSolid(planetModel, minX, maxX, minY, maxY, (minZ+maxZ) * 0.5);
-    }
-    return new StandardXYZSolid(planetModel, minX, maxX, minY, maxY, minZ, maxZ);
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYdZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYdZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYdZSolid.java
deleted file mode 100644
index e7cbe25..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYdZSolid.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in Z
- *
- * @lucene.internal
- */
-public class XYdZSolid extends BaseXYZSolid {
-
-  /** Min-X plane */
-  protected final SidedPlane minXPlane;
-  /** Max-X plane */
-  protected final SidedPlane maxXPlane;
-  /** Min-Y plane */
-  protected final SidedPlane minYPlane;
-  /** Max-Y plane */
-  protected final SidedPlane maxYPlane;
-  /** Z plane */
-  protected final Plane zPlane;
-  
-  /** These are the edge points of the shape, which are defined to be at least one point on
-   * each surface area boundary.  In the case of a solid, this includes points which represent
-   * the intersection of XYZ bounding planes and the planet, as well as points representing
-   * the intersection of single bounding planes with the planet itself.
-   */
-  protected final GeoPoint[] edgePoints;
-
-  /** Notable points for ZPlane */
-  protected final GeoPoint[] notableZPoints;
-
-  /**
-   * Sole constructor
-   *
-   *@param planetModel is the planet model.
-   *@param minX is the minimum X value.
-   *@param maxX is the maximum X value.
-   *@param minY is the minimum Y value.
-   *@param maxY is the maximum Y value.
-   *@param Z is the Z value.
-   */
-  public XYdZSolid(final PlanetModel planetModel,
-    final double minX,
-    final double maxX,
-    final double minY,
-    final double maxY,
-    final double Z) {
-    super(planetModel);
-    // Argument checking
-    if (maxX - minX < Vector.MINIMUM_RESOLUTION)
-      throw new IllegalArgumentException("X values in wrong order or identical");
-    if (maxY - minY < Vector.MINIMUM_RESOLUTION)
-      throw new IllegalArgumentException("Y values in wrong order or identical");
-
-    final double worldMinZ = planetModel.getMinimumZValue();
-    final double worldMaxZ = planetModel.getMaximumZValue();
-    
-    // Construct the planes
-    minXPlane = new SidedPlane(maxX,0.0,0.0,xUnitVector,-minX);
-    maxXPlane = new SidedPlane(minX,0.0,0.0,xUnitVector,-maxX);
-    minYPlane = new SidedPlane(0.0,maxY,0.0,yUnitVector,-minY);
-    maxYPlane = new SidedPlane(0.0,minY,0.0,yUnitVector,-maxY);
-    zPlane = new Plane(zUnitVector,-Z);
-      
-    // We need at least one point on the planet surface for each manifestation of the shape.
-    // There can be up to 2 (on opposite sides of the world).  But we have to go through
-    // 4 combinations of adjacent planes in order to find out if any have 2 intersection solution.
-    // Typically, this requires 4 square root operations. 
-    final GeoPoint[] minXZ = minXPlane.findIntersections(planetModel,zPlane,maxXPlane,minYPlane,maxYPlane);
-    final GeoPoint[] maxXZ = maxXPlane.findIntersections(planetModel,zPlane,minXPlane,minYPlane,maxYPlane);
-    final GeoPoint[] minYZ = minYPlane.findIntersections(planetModel,zPlane,maxYPlane,minXPlane,maxXPlane);
-    final GeoPoint[] maxYZ = maxYPlane.findIntersections(planetModel,zPlane,minYPlane,minXPlane,maxXPlane);
-      
-    notableZPoints = glueTogether(minXZ, maxXZ, minYZ, maxYZ);
-
-    // Now, compute the edge points.
-    // This is the trickiest part of setting up an XYZSolid.  We've computed intersections already, so
-    // we'll start there.  We know that at most there will be two disconnected shapes on the planet surface.
-    // But there's also a case where exactly one plane slices through the world, and none of the bounding plane
-    // intersections do.  Thus, if we don't find any of the edge intersection cases, we have to look for that last case.
-      
-    // If we still haven't encountered anything, we need to look at single-plane/world intersections.
-    // We detect these by looking at the world model and noting its x, y, and z bounds.
-    // The cases we are looking for are when the four corner points for any given
-    // plane are all outside of the world, AND that plane intersects the world.
-    // There are four corner points all told; we must evaluate these WRT the planet surface.
-    final boolean minXminYZ = planetModel.pointOutside(minX, minY, Z);
-    final boolean minXmaxYZ = planetModel.pointOutside(minX, maxY, Z);
-    final boolean maxXminYZ = planetModel.pointOutside(maxX, minY, Z);
-    final boolean maxXmaxYZ = planetModel.pointOutside(maxX, maxY, Z);
-
-    final GeoPoint[] zEdges;
-    if (Z - worldMinZ >= -Vector.MINIMUM_RESOLUTION && Z - worldMaxZ <= Vector.MINIMUM_RESOLUTION &&
-      minX < 0.0 && maxX > 0.0 && minY < 0.0 && maxY > 0.0 &&
-      minXminYZ && minXmaxYZ && maxXminYZ && maxXmaxYZ) {
-      // Find any point on the minZ plane that intersects the world
-      // First construct a perpendicular plane that will allow us to find a sample point.
-      // This plane is vertical and goes through the points (0,0,0) and (1,0,0)
-      // Then use it to compute a sample point.
-      final GeoPoint intPoint = zPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane);
-      if (intPoint != null) {
-        zEdges = new GeoPoint[]{intPoint};
-      } else {
-        zEdges = EMPTY_POINTS;
-      }
-    } else {
-      zEdges= EMPTY_POINTS;
-    }
-
-    this.edgePoints = glueTogether(minXZ, maxXZ, minYZ, maxYZ, zEdges);
-  }
-
-  @Override
-  protected GeoPoint[] getEdgePoints() {
-    return edgePoints;
-  }
-  
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    return minXPlane.isWithin(x, y, z) &&
-      maxXPlane.isWithin(x, y, z) &&
-      minYPlane.isWithin(x, y, z) &&
-      maxYPlane.isWithin(x, y, z) &&
-      zPlane.evaluateIsZero(x, y, z);
-  }
-
-  @Override
-  public int getRelationship(final GeoShape path) {
-    
-    //System.err.println(this+" getrelationship with "+path);
-    final int insideRectangle = isShapeInsideArea(path);
-    if (insideRectangle == SOME_INSIDE) {
-      //System.err.println(" some inside");
-      return OVERLAPS;
-    }
-
-    // Figure out if the entire XYZArea is contained by the shape.
-    final int insideShape = isAreaInsideShape(path);
-    if (insideShape == SOME_INSIDE) {
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
-      //System.err.println(" inside of each other");
-      return OVERLAPS;
-    }
-
-    if (path.intersects(zPlane, notableZPoints, minXPlane, maxXPlane, minYPlane, maxYPlane)) {
-      //System.err.println(" edges intersect");
-      return OVERLAPS;
-    }
-
-    if (insideRectangle == ALL_INSIDE) {
-      //System.err.println(" shape inside rectangle");
-      return WITHIN;
-    }
-
-    if (insideShape == ALL_INSIDE) {
-      //System.err.println(" shape contains rectangle");
-      return CONTAINS;
-    }
-    //System.err.println(" disjoint");
-    return DISJOINT;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof XYdZSolid))
-      return false;
-    XYdZSolid other = (XYdZSolid) o;
-    if (!super.equals(other)) {
-      return false;
-    }
-    return other.minXPlane.equals(minXPlane) &&
-      other.maxXPlane.equals(maxXPlane) &&
-      other.minYPlane.equals(minYPlane) &&
-      other.maxYPlane.equals(maxYPlane) &&
-      other.zPlane.equals(zPlane);
-  }
-
-  @Override
-  public int hashCode() {
-    int result = super.hashCode();
-    result = 31 * result  + minXPlane.hashCode();
-    result = 31 * result  + maxXPlane.hashCode();
-    result = 31 * result  + minYPlane.hashCode();
-    result = 31 * result  + maxYPlane.hashCode();
-    result = 31 * result  + zPlane.hashCode();
-    return result;
-  }
-
-  @Override
-  public String toString() {
-    return "XYdZSolid: {planetmodel="+planetModel+", minXplane="+minXPlane+", maxXplane="+maxXPlane+", minYplane="+minYPlane+", maxYplane="+maxYPlane+", zplane="+zPlane+"}";
-  }
-  
-}
-  


[12/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Plane.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Plane.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Plane.java
new file mode 100755
index 0000000..1f2c054
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Plane.java
@@ -0,0 +1,1657 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * We know about three kinds of planes.  First kind: general plain through two points and origin
+ * Second kind: horizontal plane at specified height.  Third kind: vertical plane with specified x and y value, through origin.
+ *
+ * @lucene.experimental
+ */
+public class Plane extends Vector {
+  /** An array with no points in it */
+  protected final static GeoPoint[] NO_POINTS = new GeoPoint[0];
+  /** An array with no bounds in it */
+  protected final static Membership[] NO_BOUNDS = new Membership[0];
+  /** A vertical plane normal to the Y axis */
+  protected final static Plane normalYPlane = new Plane(0.0,1.0,0.0,0.0);
+  /** A vertical plane normal to the X axis */
+  protected final static Plane normalXPlane = new Plane(1.0,0.0,0.0,0.0);
+  /** A vertical plane normal to the Z axis */
+  protected final static Plane normalZPlane = new Plane(0.0,0.0,1.0,0.0);
+
+  /** Ax + By + Cz + D = 0 */
+  public final double D;
+
+  /**
+   * Construct a plane with all four coefficients defined.
+   *@param A is A
+   *@param B is B
+   *@param C is C
+   *@param D is D
+   */
+  public Plane(final double A, final double B, final double C, final double D) {
+    super(A, B, C);
+    this.D = D;
+  }
+
+  /**
+   * Construct a plane through two points and origin.
+   *
+   * @param A is the first point (origin based).
+   * @param B is the second point (origin based).
+   */
+  public Plane(final Vector A, final Vector B) {
+    super(A, B);
+    D = 0.0;
+  }
+
+  /**
+   * Construct a horizontal plane at a specified Z.
+   *
+   * @param planetModel is the planet model.
+   * @param sinLat is the sin(latitude).
+   */
+  public Plane(final PlanetModel planetModel, final double sinLat) {
+    super(0.0, 0.0, 1.0);
+    D = -sinLat * computeDesiredEllipsoidMagnitude(planetModel, sinLat);
+  }
+
+  /**
+   * Construct a vertical plane through a specified
+   * x, y and origin.
+   *
+   * @param x is the specified x value.
+   * @param y is the specified y value.
+   */
+  public Plane(final double x, final double y) {
+    super(y, -x, 0.0);
+    D = 0.0;
+  }
+
+  /**
+   * Construct a plane with a specific vector, and D offset
+   * from origin.
+   * @param v is the normal vector.
+   * @param D is the D offset from the origin.
+   */
+  public Plane(final Vector v, final double D) {
+    super(v.x, v.y, v.z);
+    this.D = D;
+  }
+
+  /** Construct the most accurate normalized plane through an x-y point and including the Z axis.
+   * If none of the points can determine the plane, return null.
+   * @param planePoints is a set of points to choose from.  The best one for constructing the most precise plane is picked.
+   * @return the plane
+   */
+  public static Plane constructNormalizedZPlane(final Vector... planePoints) {
+    // Pick the best one (with the greatest x-y distance)
+    double bestDistance = 0.0;
+    Vector bestPoint = null;
+    for (final Vector point : planePoints) {
+      final double pointDist = point.x * point.x + point.y * point.y;
+      if (pointDist > bestDistance) {
+        bestDistance = pointDist;
+        bestPoint = point;
+      }
+    }
+    return constructNormalizedZPlane(bestPoint.x, bestPoint.y);
+  }
+
+  /** Construct the most accurate normalized plane through an x-z point and including the Y axis.
+   * If none of the points can determine the plane, return null.
+   * @param planePoints is a set of points to choose from.  The best one for constructing the most precise plane is picked.
+   * @return the plane
+   */
+  public static Plane constructNormalizedYPlane(final Vector... planePoints) {
+    // Pick the best one (with the greatest x-z distance)
+    double bestDistance = 0.0;
+    Vector bestPoint = null;
+    for (final Vector point : planePoints) {
+      final double pointDist = point.x * point.x + point.z * point.z;
+      if (pointDist > bestDistance) {
+        bestDistance = pointDist;
+        bestPoint = point;
+      }
+    }
+    return constructNormalizedYPlane(bestPoint.x, bestPoint.z, 0.0);
+  }
+
+  /** Construct the most accurate normalized plane through an y-z point and including the X axis.
+   * If none of the points can determine the plane, return null.
+   * @param planePoints is a set of points to choose from.  The best one for constructing the most precise plane is picked.
+   * @return the plane
+   */
+  public static Plane constructNormalizedXPlane(final Vector... planePoints) {
+    // Pick the best one (with the greatest y-z distance)
+    double bestDistance = 0.0;
+    Vector bestPoint = null;
+    for (final Vector point : planePoints) {
+      final double pointDist = point.y * point.y + point.z * point.z;
+      if (pointDist > bestDistance) {
+        bestDistance = pointDist;
+        bestPoint = point;
+      }
+    }
+    return constructNormalizedXPlane(bestPoint.y, bestPoint.z, 0.0);
+  }
+
+  /** Construct a normalized plane through an x-y point and including the Z axis.
+   * If the x-y point is at (0,0), return null.
+   * @param x is the x value.
+   * @param y is the y value.
+   * @return a plane passing through the Z axis and (x,y,0).
+   */
+  public static Plane constructNormalizedZPlane(final double x, final double y) {
+    if (Math.abs(x) < MINIMUM_RESOLUTION && Math.abs(y) < MINIMUM_RESOLUTION)
+      return null;
+    final double denom = 1.0 / Math.sqrt(x*x + y*y);
+    return new Plane(y * denom, -x * denom, 0.0, 0.0);
+  }
+
+  /** Construct a normalized plane through an x-z point and parallel to the Y axis.
+   * If the x-z point is at (0,0), return null.
+   * @param x is the x value.
+   * @param z is the z value.
+   * @param DValue is the offset from the origin for the plane.
+   * @return a plane parallel to the Y axis and perpendicular to the x and z values given.
+   */
+  public static Plane constructNormalizedYPlane(final double x, final double z, final double DValue) {
+    if (Math.abs(x) < MINIMUM_RESOLUTION && Math.abs(z) < MINIMUM_RESOLUTION)
+      return null;
+    final double denom = 1.0 / Math.sqrt(x*x + z*z);
+    return new Plane(z * denom, 0.0, -x * denom, DValue);
+  }
+
+  /** Construct a normalized plane through a y-z point and parallel to the X axis.
+   * If the y-z point is at (0,0), return null.
+   * @param y is the y value.
+   * @param z is the z value.
+   * @param DValue is the offset from the origin for the plane.
+   * @return a plane parallel to the X axis and perpendicular to the y and z values given.
+   */
+  public static Plane constructNormalizedXPlane(final double y, final double z, final double DValue) {
+    if (Math.abs(y) < MINIMUM_RESOLUTION && Math.abs(z) < MINIMUM_RESOLUTION)
+      return null;
+    final double denom = 1.0 / Math.sqrt(y*y + z*z);
+    return new Plane(0.0, z * denom, -y * denom, DValue);
+  }
+  
+  /**
+   * Evaluate the plane equation for a given point, as represented
+   * by a vector.
+   *
+   * @param v is the vector.
+   * @return the result of the evaluation.
+   */
+  public double evaluate(final Vector v) {
+    return dotProduct(v) + D;
+  }
+
+  /**
+   * Evaluate the plane equation for a given point, as represented
+   * by a vector.
+   * @param x is the x value.
+   * @param y is the y value.
+   * @param z is the z value.
+   * @return the result of the evaluation.
+   */
+  public double evaluate(final double x, final double y, final double z) {
+    return dotProduct(x, y, z) + D;
+  }
+
+  /**
+   * Evaluate the plane equation for a given point, as represented
+   * by a vector.
+   *
+   * @param v is the vector.
+   * @return true if the result is on the plane.
+   */
+  public boolean evaluateIsZero(final Vector v) {
+    return Math.abs(evaluate(v)) < MINIMUM_RESOLUTION;
+  }
+
+  /**
+   * Evaluate the plane equation for a given point, as represented
+   * by a vector.
+   *
+   * @param x is the x value.
+   * @param y is the y value.
+   * @param z is the z value.
+   * @return true if the result is on the plane.
+   */
+  public boolean evaluateIsZero(final double x, final double y, final double z) {
+    return Math.abs(evaluate(x, y, z)) < MINIMUM_RESOLUTION;
+  }
+
+  /**
+   * Build a normalized plane, so that the vector is normalized.
+   *
+   * @return the normalized plane object, or null if the plane is indeterminate.
+   */
+  public Plane normalize() {
+    Vector normVect = super.normalize();
+    if (normVect == null)
+      return null;
+    return new Plane(normVect, this.D);
+  }
+
+  /** Compute arc distance from plane to a vector expressed with a {@link GeoPoint}.
+   *  @see #arcDistance(PlanetModel, double, double, double, Membership...) */
+  public double arcDistance(final PlanetModel planetModel, final GeoPoint v, final Membership... bounds) {
+    return arcDistance(planetModel, v.x, v.y, v.z, bounds);
+  }
+    
+  /**
+   * Compute arc distance from plane to a vector.
+   * @param planetModel is the planet model.
+   * @param x is the x vector value.
+   * @param y is the y vector value.
+   * @param z is the z vector value.
+   * @param bounds are the bounds which constrain the intersection point.
+   * @return the arc distance.
+   */
+  public double arcDistance(final PlanetModel planetModel, final double x, final double y, final double z, final Membership... bounds) {
+
+    if (evaluateIsZero(x,y,z)) {
+      if (meetsAllBounds(x,y,z, bounds))
+        return 0.0;
+      return Double.MAX_VALUE;
+    }
+    
+    // First, compute the perpendicular plane.
+    final Plane perpPlane = new Plane(this.y * z - this.z * y, this.z * x - this.x * z, this.x * y - this.y * x, 0.0);
+
+    // We need to compute the intersection of two planes on the geo surface: this one, and its perpendicular.
+    // Then, we need to choose which of the two points we want to compute the distance to.  We pick the
+    // shorter distance always.
+    
+    final GeoPoint[] intersectionPoints = findIntersections(planetModel, perpPlane);
+    
+    // For each point, compute a linear distance, and take the minimum of them
+    double minDistance = Double.MAX_VALUE;
+    
+    for (final GeoPoint intersectionPoint : intersectionPoints) {
+      if (meetsAllBounds(intersectionPoint, bounds)) {
+        final double theDistance = intersectionPoint.arcDistance(x,y,z);
+        if (theDistance < minDistance) {
+          minDistance = theDistance;
+        }
+      }
+    }
+    return minDistance;
+
+  }
+
+  /**
+   * Compute normal distance from plane to a vector.
+   * @param v is the vector.
+   * @param bounds are the bounds which constrain the intersection point.
+   * @return the normal distance.
+   */
+  public double normalDistance(final Vector v, final Membership... bounds) {
+    return normalDistance(v.x, v.y, v.z, bounds);
+  }
+    
+  /**
+   * Compute normal distance from plane to a vector.
+   * @param x is the vector x.
+   * @param y is the vector y.
+   * @param z is the vector z.
+   * @param bounds are the bounds which constrain the intersection point.
+   * @return the normal distance.
+   */
+  public double normalDistance(final double x, final double y, final double z, final Membership... bounds) {
+
+    final double dist = evaluate(x,y,z);
+    final double perpX = x - dist * this.x;
+    final double perpY = y - dist * this.y;
+    final double perpZ = z - dist * this.z;
+
+    if (!meetsAllBounds(perpX, perpY, perpZ, bounds)) {
+      return Double.MAX_VALUE;
+    }
+    
+    return Math.abs(dist);
+  }
+  
+  /**
+   * Compute normal distance squared from plane to a vector.
+   * @param v is the vector.
+   * @param bounds are the bounds which constrain the intersection point.
+   * @return the normal distance squared.
+   */
+  public double normalDistanceSquared(final Vector v, final Membership... bounds) {
+    return normalDistanceSquared(v.x, v.y, v.z, bounds);
+  }
+  
+  /**
+   * Compute normal distance squared from plane to a vector.
+   * @param x is the vector x.
+   * @param y is the vector y.
+   * @param z is the vector z.
+   * @param bounds are the bounds which constrain the intersection point.
+   * @return the normal distance squared.
+   */
+  public double normalDistanceSquared(final double x, final double y, final double z, final Membership... bounds) {
+    final double normal = normalDistance(x,y,z,bounds);
+    if (normal == Double.MAX_VALUE)
+      return normal;
+    return normal * normal;
+  }
+
+  /**
+   * Compute linear distance from plane to a vector.  This is defined
+   * as the distance from the given point to the nearest intersection of 
+   * this plane with the planet surface.
+   * @param planetModel is the planet model.
+   * @param v is the point.
+   * @param bounds are the bounds which constrain the intersection point.
+   * @return the linear distance.
+   */
+  public double linearDistance(final PlanetModel planetModel, final GeoPoint v, final Membership... bounds) {
+    return linearDistance(planetModel, v.x, v.y, v.z, bounds);
+  }
+    
+  /**
+   * Compute linear distance from plane to a vector.  This is defined
+   * as the distance from the given point to the nearest intersection of 
+   * this plane with the planet surface.
+   * @param planetModel is the planet model.
+   * @param x is the vector x.
+   * @param y is the vector y.
+   * @param z is the vector z.
+   * @param bounds are the bounds which constrain the intersection point.
+   * @return the linear distance.
+   */
+  public double linearDistance(final PlanetModel planetModel, final double x, final double y, final double z, final Membership... bounds) {
+    if (evaluateIsZero(x,y,z)) {
+      if (meetsAllBounds(x,y,z, bounds))
+        return 0.0;
+      return Double.MAX_VALUE;
+    }
+    
+    // First, compute the perpendicular plane.
+    final Plane perpPlane = new Plane(this.y * z - this.z * y, this.z * x - this.x * z, this.x * y - this.y * x, 0.0);
+
+    // We need to compute the intersection of two planes on the geo surface: this one, and its perpendicular.
+    // Then, we need to choose which of the two points we want to compute the distance to.  We pick the
+    // shorter distance always.
+    
+    final GeoPoint[] intersectionPoints = findIntersections(planetModel, perpPlane);
+    
+    // For each point, compute a linear distance, and take the minimum of them
+    double minDistance = Double.MAX_VALUE;
+    
+    for (final GeoPoint intersectionPoint : intersectionPoints) {
+      if (meetsAllBounds(intersectionPoint, bounds)) {
+        final double theDistance = intersectionPoint.linearDistance(x,y,z);
+        if (theDistance < minDistance) {
+          minDistance = theDistance;
+        }
+      }
+    }
+    return minDistance;
+  }
+      
+  /**
+   * Compute linear distance squared from plane to a vector.  This is defined
+   * as the distance from the given point to the nearest intersection of 
+   * this plane with the planet surface.
+   * @param planetModel is the planet model.
+   * @param v is the point.
+   * @param bounds are the bounds which constrain the intersection point.
+   * @return the linear distance squared.
+   */
+  public double linearDistanceSquared(final PlanetModel planetModel, final GeoPoint v, final Membership... bounds) {
+    return linearDistanceSquared(planetModel, v.x, v.y, v.z, bounds);
+  }
+  
+  /**
+   * Compute linear distance squared from plane to a vector.  This is defined
+   * as the distance from the given point to the nearest intersection of 
+   * this plane with the planet surface.
+   * @param planetModel is the planet model.
+   * @param x is the vector x.
+   * @param y is the vector y.
+   * @param z is the vector z.
+   * @param bounds are the bounds which constrain the intersection point.
+   * @return the linear distance squared.
+   */
+  public double linearDistanceSquared(final PlanetModel planetModel, final double x, final double y, final double z, final Membership... bounds) {
+    final double linearDistance = linearDistance(planetModel, x, y, z, bounds);
+    return linearDistance * linearDistance;
+  }
+
+  /**
+   * Find points on the boundary of the intersection of a plane and the unit sphere,
+   * given a starting point, and ending point, and a list of proportions of the arc (e.g. 0.25, 0.5, 0.75).
+   * The angle between the starting point and ending point is assumed to be less than pi.
+   * @param start is the start point.
+   * @param end is the end point.
+   * @param proportions is an array of fractional proportions measured between start and end.
+   * @return an array of points corresponding to the proportions passed in.
+   */
+  public GeoPoint[] interpolate(final GeoPoint start, final GeoPoint end, final double[] proportions) {
+    // Steps:
+    // (1) Translate (x0,y0,z0) of endpoints into origin-centered place:
+    // x1 = x0 + D*A
+    // y1 = y0 + D*B
+    // z1 = z0 + D*C
+    // (2) Rotate counterclockwise in x-y:
+    // ra = -atan2(B,A)
+    // x2 = x1 cos ra - y1 sin ra
+    // y2 = x1 sin ra + y1 cos ra
+    // z2 = z1
+    // Faster:
+    // cos ra = A/sqrt(A^2+B^2+C^2)
+    // sin ra = -B/sqrt(A^2+B^2+C^2)
+    // cos (-ra) = A/sqrt(A^2+B^2+C^2)
+    // sin (-ra) = B/sqrt(A^2+B^2+C^2)
+    // (3) Rotate clockwise in x-z:
+    // ha = pi/2 - asin(C/sqrt(A^2+B^2+C^2))
+    // x3 = x2 cos ha - z2 sin ha
+    // y3 = y2
+    // z3 = x2 sin ha + z2 cos ha
+    // At this point, z3 should be zero.
+    // Faster:
+    // sin(ha) = cos(asin(C/sqrt(A^2+B^2+C^2))) = sqrt(1 - C^2/(A^2+B^2+C^2)) = sqrt(A^2+B^2)/sqrt(A^2+B^2+C^2)
+    // cos(ha) = sin(asin(C/sqrt(A^2+B^2+C^2))) = C/sqrt(A^2+B^2+C^2)
+    // (4) Compute interpolations by getting longitudes of original points
+    // la = atan2(y3,x3)
+    // (5) Rotate new points (xN0, yN0, zN0) counter-clockwise in x-z:
+    // ha = -(pi - asin(C/sqrt(A^2+B^2+C^2)))
+    // xN1 = xN0 cos ha - zN0 sin ha
+    // yN1 = yN0
+    // zN1 = xN0 sin ha + zN0 cos ha
+    // (6) Rotate new points clockwise in x-y:
+    // ra = atan2(B,A)
+    // xN2 = xN1 cos ra - yN1 sin ra
+    // yN2 = xN1 sin ra + yN1 cos ra
+    // zN2 = zN1
+    // (7) Translate new points:
+    // xN3 = xN2 - D*A
+    // yN3 = yN2 - D*B
+    // zN3 = zN2 - D*C
+
+    // First, calculate the angles and their sin/cos values
+    double A = x;
+    double B = y;
+    double C = z;
+
+    // Translation amounts
+    final double transX = -D * A;
+    final double transY = -D * B;
+    final double transZ = -D * C;
+
+    double cosRA;
+    double sinRA;
+    double cosHA;
+    double sinHA;
+
+    double magnitude = magnitude();
+    if (magnitude >= MINIMUM_RESOLUTION) {
+      final double denom = 1.0 / magnitude;
+      A *= denom;
+      B *= denom;
+      C *= denom;
+
+      // cos ra = A/sqrt(A^2+B^2+C^2)
+      // sin ra = -B/sqrt(A^2+B^2+C^2)
+      // cos (-ra) = A/sqrt(A^2+B^2+C^2)
+      // sin (-ra) = B/sqrt(A^2+B^2+C^2)
+      final double xyMagnitude = Math.sqrt(A * A + B * B);
+      if (xyMagnitude >= MINIMUM_RESOLUTION) {
+        final double xyDenom = 1.0 / xyMagnitude;
+        cosRA = A * xyDenom;
+        sinRA = -B * xyDenom;
+      } else {
+        cosRA = 1.0;
+        sinRA = 0.0;
+      }
+
+      // sin(ha) = cos(asin(C/sqrt(A^2+B^2+C^2))) = sqrt(1 - C^2/(A^2+B^2+C^2)) = sqrt(A^2+B^2)/sqrt(A^2+B^2+C^2)
+      // cos(ha) = sin(asin(C/sqrt(A^2+B^2+C^2))) = C/sqrt(A^2+B^2+C^2)
+      sinHA = xyMagnitude;
+      cosHA = C;
+    } else {
+      cosRA = 1.0;
+      sinRA = 0.0;
+      cosHA = 1.0;
+      sinHA = 0.0;
+    }
+
+    // Forward-translate the start and end points
+    final Vector modifiedStart = modify(start, transX, transY, transZ, sinRA, cosRA, sinHA, cosHA);
+    final Vector modifiedEnd = modify(end, transX, transY, transZ, sinRA, cosRA, sinHA, cosHA);
+    if (Math.abs(modifiedStart.z) >= MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("Start point was not on plane: " + modifiedStart.z);
+    if (Math.abs(modifiedEnd.z) >= MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("End point was not on plane: " + modifiedEnd.z);
+
+    // Compute the angular distance between start and end point
+    final double startAngle = Math.atan2(modifiedStart.y, modifiedStart.x);
+    final double endAngle = Math.atan2(modifiedEnd.y, modifiedEnd.x);
+
+    final double startMagnitude = Math.sqrt(modifiedStart.x * modifiedStart.x + modifiedStart.y * modifiedStart.y);
+    double delta;
+
+    double newEndAngle = endAngle;
+    while (newEndAngle < startAngle) {
+      newEndAngle += Math.PI * 2.0;
+    }
+
+    if (newEndAngle - startAngle <= Math.PI) {
+      delta = newEndAngle - startAngle;
+    } else {
+      double newStartAngle = startAngle;
+      while (newStartAngle < endAngle) {
+        newStartAngle += Math.PI * 2.0;
+      }
+      delta = newStartAngle - endAngle;
+    }
+
+    final GeoPoint[] returnValues = new GeoPoint[proportions.length];
+    for (int i = 0; i < returnValues.length; i++) {
+      final double newAngle = startAngle + proportions[i] * delta;
+      final double sinNewAngle = Math.sin(newAngle);
+      final double cosNewAngle = Math.cos(newAngle);
+      final Vector newVector = new Vector(cosNewAngle * startMagnitude, sinNewAngle * startMagnitude, 0.0);
+      returnValues[i] = reverseModify(newVector, transX, transY, transZ, sinRA, cosRA, sinHA, cosHA);
+    }
+
+    return returnValues;
+  }
+
+  /**
+   * Modify a point to produce a vector in translated/rotated space.
+   * @param start is the start point.
+   * @param transX is the translation x value.
+   * @param transY is the translation y value.
+   * @param transZ is the translation z value.
+   * @param sinRA is the sine of the ascension angle.
+   * @param cosRA is the cosine of the ascension angle.
+   * @param sinHA is the sine of the height angle.
+   * @param cosHA is the cosine of the height angle.
+   * @return the modified point.
+   */
+  protected static Vector modify(final GeoPoint start, final double transX, final double transY, final double transZ,
+                                 final double sinRA, final double cosRA, final double sinHA, final double cosHA) {
+    return start.translate(transX, transY, transZ).rotateXY(sinRA, cosRA).rotateXZ(sinHA, cosHA);
+  }
+
+  /**
+   * Reverse modify a point to produce a GeoPoint in normal space.
+   * @param point is the translated point.
+   * @param transX is the translation x value.
+   * @param transY is the translation y value.
+   * @param transZ is the translation z value.
+   * @param sinRA is the sine of the ascension angle.
+   * @param cosRA is the cosine of the ascension angle.
+   * @param sinHA is the sine of the height angle.
+   * @param cosHA is the cosine of the height angle.
+   * @return the original point.
+   */
+  protected static GeoPoint reverseModify(final Vector point, final double transX, final double transY, final double transZ,
+                                          final double sinRA, final double cosRA, final double sinHA, final double cosHA) {
+    final Vector result = point.rotateXZ(-sinHA, cosHA).rotateXY(-sinRA, cosRA).translate(-transX, -transY, -transZ);
+    return new GeoPoint(result.x, result.y, result.z);
+  }
+
+  /**
+   * Public version of findIntersections.
+   * @param planetModel is the planet model.
+   * @param q is the plane to intersect with.
+   * @param bounds are the bounds to consider to determine legal intersection points.
+   * @return the set of legal intersection points.
+   */
+  public GeoPoint[] findIntersections(final PlanetModel planetModel, final Plane q, final Membership... bounds) {
+    if (isNumericallyIdentical(q)) {
+      return null;
+    }
+    return findIntersections(planetModel, q, bounds, NO_BOUNDS);
+  }
+  
+  /**
+   * Find the intersection points between two planes, given a set of bounds.
+   *
+   * @param planetModel is the planet model to use in finding points.
+   * @param q          is the plane to intersect with.
+   * @param bounds     is the set of bounds.
+   * @param moreBounds is another set of bounds.
+   * @return the intersection point(s) on the unit sphere, if there are any.
+   */
+  protected GeoPoint[] findIntersections(final PlanetModel planetModel, final Plane q, final Membership[] bounds, final Membership[] moreBounds) {
+    //System.err.println("Looking for intersection between plane "+this+" and plane "+q+" within bounds");
+    // Unnormalized, unchecked...
+    final Vector lineVector = new Vector(y * q.z - z * q.y, z * q.x - x * q.z, x * q.y - y * q.x);
+    if (Math.abs(lineVector.x) < MINIMUM_RESOLUTION && Math.abs(lineVector.y) < MINIMUM_RESOLUTION && Math.abs(lineVector.z) < MINIMUM_RESOLUTION) {
+      // Degenerate case: parallel planes
+      //System.err.println(" planes are parallel - no intersection");
+      return NO_POINTS;
+    }
+
+    // The line will have the equation: A t + A0 = x, B t + B0 = y, C t + C0 = z.
+    // We have A, B, and C.  In order to come up with A0, B0, and C0, we need to find a point that is on both planes.
+    // To do this, we find the largest vector value (either x, y, or z), and look for a point that solves both plane equations
+    // simultaneous.  For example, let's say that the vector is (0.5,0.5,1), and the two plane equations are:
+    // 0.7 x + 0.3 y + 0.1 z + 0.0 = 0
+    // and
+    // 0.9 x - 0.1 y + 0.2 z + 4.0 = 0
+    // Then we'd pick z = 0, so the equations to solve for x and y would be:
+    // 0.7 x + 0.3y = 0.0
+    // 0.9 x - 0.1y = -4.0
+    // ... which can readily be solved using standard linear algebra.  Generally:
+    // Q0 x + R0 y = S0
+    // Q1 x + R1 y = S1
+    // ... can be solved by Cramer's rule:
+    // x = det(S0 R0 / S1 R1) / det(Q0 R0 / Q1 R1)
+    // y = det(Q0 S0 / Q1 S1) / det(Q0 R0 / Q1 R1)
+    // ... where det( a b / c d ) = ad - bc, so:
+    // x = (S0 * R1 - R0 * S1) / (Q0 * R1 - R0 * Q1)
+    // y = (Q0 * S1 - S0 * Q1) / (Q0 * R1 - R0 * Q1)
+    double x0;
+    double y0;
+    double z0;
+    // We try to maximize the determinant in the denominator
+    final double denomYZ = this.y * q.z - this.z * q.y;
+    final double denomXZ = this.x * q.z - this.z * q.x;
+    final double denomXY = this.x * q.y - this.y * q.x;
+    if (Math.abs(denomYZ) >= Math.abs(denomXZ) && Math.abs(denomYZ) >= Math.abs(denomXY)) {
+      // X is the biggest, so our point will have x0 = 0.0
+      if (Math.abs(denomYZ) < MINIMUM_RESOLUTION_SQUARED) {
+        //System.err.println(" Denominator is zero: no intersection");
+        return NO_POINTS;
+      }
+      final double denom = 1.0 / denomYZ;
+      x0 = 0.0;
+      y0 = (-this.D * q.z - this.z * -q.D) * denom;
+      z0 = (this.y * -q.D + this.D * q.y) * denom;
+    } else if (Math.abs(denomXZ) >= Math.abs(denomXY) && Math.abs(denomXZ) >= Math.abs(denomYZ)) {
+      // Y is the biggest, so y0 = 0.0
+      if (Math.abs(denomXZ) < MINIMUM_RESOLUTION_SQUARED) {
+        //System.err.println(" Denominator is zero: no intersection");
+        return NO_POINTS;
+      }
+      final double denom = 1.0 / denomXZ;
+      x0 = (-this.D * q.z - this.z * -q.D) * denom;
+      y0 = 0.0;
+      z0 = (this.x * -q.D + this.D * q.x) * denom;
+    } else {
+      // Z is the biggest, so Z0 = 0.0
+      if (Math.abs(denomXY) < MINIMUM_RESOLUTION_SQUARED) {
+        //System.err.println(" Denominator is zero: no intersection");
+        return NO_POINTS;
+      }
+      final double denom = 1.0 / denomXY;
+      x0 = (-this.D * q.y - this.y * -q.D) * denom;
+      y0 = (this.x * -q.D + this.D * q.x) * denom;
+      z0 = 0.0;
+    }
+
+    // Once an intersecting line is determined, the next step is to intersect that line with the ellipsoid, which
+    // will yield zero, one, or two points.
+    // The ellipsoid equation: 1,0 = x^2/a^2 + y^2/b^2 + z^2/c^2
+    // 1.0 = (At+A0)^2/a^2 + (Bt+B0)^2/b^2 + (Ct+C0)^2/c^2
+    // A^2 t^2 / a^2 + 2AA0t / a^2 + A0^2 / a^2 + B^2 t^2 / b^2 + 2BB0t / b^2 + B0^2 / b^2 + C^2 t^2 / c^2 + 2CC0t / c^2 + C0^2 / c^2  - 1,0 = 0.0
+    // [A^2 / a^2 + B^2 / b^2 + C^2 / c^2] t^2 + [2AA0 / a^2 + 2BB0 / b^2 + 2CC0 / c^2] t + [A0^2 / a^2 + B0^2 / b^2 + C0^2 / c^2 - 1,0] = 0.0
+    // Use the quadratic formula to determine t values and candidate point(s)
+    final double A = lineVector.x * lineVector.x * planetModel.inverseAbSquared +
+      lineVector.y * lineVector.y * planetModel.inverseAbSquared +
+      lineVector.z * lineVector.z * planetModel.inverseCSquared;
+    final double B = 2.0 * (lineVector.x * x0 * planetModel.inverseAbSquared + lineVector.y * y0 * planetModel.inverseAbSquared + lineVector.z * z0 * planetModel.inverseCSquared);
+    final double C = x0 * x0 * planetModel.inverseAbSquared + y0 * y0 * planetModel.inverseAbSquared + z0 * z0 * planetModel.inverseCSquared - 1.0;
+
+    final double BsquaredMinus = B * B - 4.0 * A * C;
+    if (Math.abs(BsquaredMinus) < MINIMUM_RESOLUTION_SQUARED) {
+      //System.err.println(" One point of intersection");
+      final double inverse2A = 1.0 / (2.0 * A);
+      // One solution only
+      final double t = -B * inverse2A;
+      GeoPoint point = new GeoPoint(lineVector.x * t + x0, lineVector.y * t + y0, lineVector.z * t + z0);
+      //System.err.println("  point: "+point);
+      //verifyPoint(planetModel, point, q);
+      if (point.isWithin(bounds, moreBounds))
+        return new GeoPoint[]{point};
+      return NO_POINTS;
+    } else if (BsquaredMinus > 0.0) {
+      //System.err.println(" Two points of intersection");
+      final double inverse2A = 1.0 / (2.0 * A);
+      // Two solutions
+      final double sqrtTerm = Math.sqrt(BsquaredMinus);
+      final double t1 = (-B + sqrtTerm) * inverse2A;
+      final double t2 = (-B - sqrtTerm) * inverse2A;
+      GeoPoint point1 = new GeoPoint(lineVector.x * t1 + x0, lineVector.y * t1 + y0, lineVector.z * t1 + z0);
+      GeoPoint point2 = new GeoPoint(lineVector.x * t2 + x0, lineVector.y * t2 + y0, lineVector.z * t2 + z0);
+      //verifyPoint(planetModel, point1, q);
+      //verifyPoint(planetModel, point2, q);
+      //System.err.println("  "+point1+" and "+point2);
+      if (point1.isWithin(bounds, moreBounds)) {
+        if (point2.isWithin(bounds, moreBounds))
+          return new GeoPoint[]{point1, point2};
+        return new GeoPoint[]{point1};
+      }
+      if (point2.isWithin(bounds, moreBounds))
+        return new GeoPoint[]{point2};
+      return NO_POINTS;
+    } else {
+      //System.err.println(" no solutions - no intersection");
+      return NO_POINTS;
+    }
+  }
+
+  /*
+  protected void verifyPoint(final PlanetModel planetModel, final GeoPoint point, final Plane q) {
+    if (!evaluateIsZero(point))
+      throw new RuntimeException("Intersection point not on original plane; point="+point+", plane="+this);
+    if (!q.evaluateIsZero(point))
+      throw new RuntimeException("Intersection point not on intersected plane; point="+point+", plane="+q);
+    if (Math.abs(point.x * point.x * planetModel.inverseASquared + point.y * point.y * planetModel.inverseBSquared + point.z * point.z * planetModel.inverseCSquared - 1.0) >= MINIMUM_RESOLUTION) 
+      throw new RuntimeException("Intersection point not on ellipsoid; point="+point);
+  }
+  */
+
+  /**
+   * Accumulate (x,y,z) bounds information for this plane, intersected with the unit sphere.
+   * Updates min/max information, using max/min points found
+   * within the specified bounds.
+   *
+   * @param planetModel is the planet model to use in determining bounds.
+   * @param boundsInfo is the xyz info to update with additional bounding information.
+   * @param bounds     are the surfaces delineating what's inside the shape.
+   */
+  public void recordBounds(final PlanetModel planetModel, final XYZBounds boundsInfo, final Membership... bounds) {
+    // Basic plan is to do three intersections of the plane and the planet.
+    // For min/max x, we intersect a vertical plane such that y = 0.
+    // For min/max y, we intersect a vertical plane such that x = 0.
+    // For min/max z, we intersect a vertical plane that is chosen to go through the high point of the arc.
+    // For clarity, load local variables with good names
+    final double A = this.x;
+    final double B = this.y;
+    final double C = this.z;
+
+    // Do Z.  This can be done simply because it is symmetrical.
+    if (!boundsInfo.isSmallestMinZ(planetModel) || !boundsInfo.isLargestMaxZ(planetModel)) {
+      //System.err.println("    computing Z bound");
+      // Compute Z bounds for this arc
+      // With ellipsoids, we really have only one viable way to do this computation.
+      // Specifically, we compute an appropriate vertical plane, based on the current plane's x-y orientation, and
+      // then intersect it with this one and with the ellipsoid.  This gives us zero, one, or two points to use
+      // as bounds.
+      // There is one special case: horizontal circles.  These require TWO vertical planes: one for the x, and one for
+      // the y, and we use all four resulting points in the bounds computation.
+      if ((Math.abs(A) >= MINIMUM_RESOLUTION || Math.abs(B) >= MINIMUM_RESOLUTION)) {
+        // NOT a degenerate case
+        //System.err.println("    not degenerate");
+        final Plane normalizedZPlane = constructNormalizedZPlane(A,B);
+        final GeoPoint[] points = findIntersections(planetModel, normalizedZPlane, bounds, NO_BOUNDS);
+        for (final GeoPoint point : points) {
+          assert planetModel.pointOnSurface(point);
+          //System.err.println("      Point = "+point+"; this.evaluate(point)="+this.evaluate(point)+"; normalizedZPlane.evaluate(point)="+normalizedZPlane.evaluate(point));
+          addPoint(boundsInfo, bounds, point);
+        }
+      } else {
+        // Since a==b==0, any plane including the Z axis suffices.
+        //System.err.println("      Perpendicular to z");
+        final GeoPoint[] points = findIntersections(planetModel, normalYPlane, NO_BOUNDS, NO_BOUNDS);
+        boundsInfo.addZValue(points[0]);
+      }
+    }
+
+    // First, compute common subexpressions
+    final double k = 1.0 / ((x*x + y*y)*planetModel.ab*planetModel.ab + z*z*planetModel.c*planetModel.c);
+    final double abSquared = planetModel.ab * planetModel.ab;
+    final double cSquared = planetModel.c * planetModel.c;
+    final double ASquared = A * A;
+    final double BSquared = B * B;
+    final double CSquared = C * C;
+    
+    final double r = 2.0*D*k;
+    final double rSquared = r * r;
+    
+    if (!boundsInfo.isSmallestMinX(planetModel) || !boundsInfo.isLargestMaxX(planetModel)) {
+      // For min/max x, we need to use lagrange multipliers.
+      //
+      // For this, we need grad(F(x,y,z)) = (dF/dx, dF/dy, dF/dz).
+      //
+      // Minimize and maximize f(x,y,z) = x, with respect to g(x,y,z) = Ax + By + Cz - D and h(x,y,z) = x^2/ab^2 + y^2/ab^2 + z^2/c^2 - 1
+      //
+      // grad(f(x,y,z)) = (1,0,0)
+      // grad(g(x,y,z)) = (A,B,C)
+      // grad(h(x,y,z)) = (2x/ab^2,2y/ab^2,2z/c^2)
+      //
+      // Equations we need to simultaneously solve:
+      // 
+      // grad(f(x,y,z)) = l * grad(g(x,y,z)) + m * grad(h(x,y,z))
+      // g(x,y,z) = 0
+      // h(x,y,z) = 0
+      // 
+      // Equations:
+      // 1 = l*A + m*2x/ab^2
+      // 0 = l*B + m*2y/ab^2
+      // 0 = l*C + m*2z/c^2
+      // Ax + By + Cz + D = 0
+      // x^2/ab^2 + y^2/ab^2 + z^2/c^2 - 1 = 0
+      // 
+      // Solve for x,y,z in terms of (l, m):
+      // 
+      // x = ((1 - l*A) * ab^2 ) / (2 * m)
+      // y = (-l*B * ab^2) / ( 2 * m)
+      // z = (-l*C * c^2)/ (2 * m)
+      // 
+      // Two equations, two unknowns:
+      // 
+      // A * (((1 - l*A) * ab^2 ) / (2 * m)) + B * ((-l*B * ab^2) / ( 2 * m)) + C * ((-l*C * c^2)/ (2 * m)) + D = 0
+      // 
+      // and
+      // 
+      // (((1 - l*A) * ab^2 ) / (2 * m))^2/ab^2 + ((-l*B * ab^2) / ( 2 * m))^2/ab^2 + ((-l*C * c^2)/ (2 * m))^2/c^2 - 1 = 0
+      // 
+      // Simple: solve for l and m, then find x from it.
+      // 
+      // (a) Use first equation to find l in terms of m.
+      // 
+      // A * (((1 - l*A) * ab^2 ) / (2 * m)) + B * ((-l*B * ab^2) / ( 2 * m)) + C * ((-l*C * c^2)/ (2 * m)) + D = 0
+      // A * ((1 - l*A) * ab^2 ) + B * (-l*B * ab^2) + C * (-l*C * c^2) + D * 2 * m = 0
+      // A * ab^2 - l*A^2* ab^2 - B^2 * l * ab^2 - C^2 * l * c^2 + D * 2 * m = 0
+      // - l *(A^2* ab^2 + B^2 * ab^2 + C^2 * c^2) + (A * ab^2 + D * 2 * m) = 0
+      // l = (A * ab^2 + D * 2 * m) / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2)
+      // l = A * ab^2 / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2) + m * 2 * D / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2)
+      // 
+      // For convenience:
+      // 
+      // k = 1.0 / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2)
+      // 
+      // Then:
+      // 
+      // l = A * ab^2 * k + m * 2 * D * k
+      // l = k * (A*ab^2 + m*2*D)
+      //
+      // For further convenience:
+      //
+      // q = A*ab^2*k
+      // r = 2*D*k
+      //
+      // l = (r*m + q)
+      // l^2 = (r^2 * m^2 + 2*r*m*q + q^2)
+      // 
+      // (b) Simplify the second equation before substitution
+      // 
+      // (((1 - l*A) * ab^2 ) / (2 * m))^2/ab^2 + ((-l*B * ab^2) / ( 2 * m))^2/ab^2 + ((-l*C * c^2)/ (2 * m))^2/c^2 - 1 = 0
+      // ((1 - l*A) * ab^2 )^2/ab^2 + (-l*B * ab^2)^2/ab^2 + (-l*C * c^2)^2/c^2 = 4 * m^2
+      // (1 - l*A)^2 * ab^2 + (-l*B)^2 * ab^2 + (-l*C)^2 * c^2 = 4 * m^2
+      // (1 - 2*l*A + l^2*A^2) * ab^2 + l^2*B^2 * ab^2 + l^2*C^2 * c^2 = 4 * m^2
+      // ab^2 - 2*A*ab^2*l + A^2*ab^2*l^2 + B^2*ab^2*l^2 + C^2*c^2*l^2 - 4*m^2 = 0
+      // 
+      // (c) Substitute for l, l^2
+      //
+      // ab^2 - 2*A*ab^2*(r*m + q) + A^2*ab^2*(r^2 * m^2 + 2*r*m*q + q^2) + B^2*ab^2*(r^2 * m^2 + 2*r*m*q + q^2) + C^2*c^2*(r^2 * m^2 + 2*r*m*q + q^2) - 4*m^2 = 0
+      // ab^2 - 2*A*ab^2*r*m - 2*A*ab^2*q + A^2*ab^2*r^2*m^2 + 2*A^2*ab^2*r*q*m +
+      //        A^2*ab^2*q^2 + B^2*ab^2*r^2*m^2 + 2*B^2*ab^2*r*q*m + B^2*ab^2*q^2 + C^2*c^2*r^2*m^2 + 2*C^2*c^2*r*q*m + C^2*c^2*q^2 - 4*m^2 = 0
+      //
+      // (d) Group
+      //
+      // m^2 * [A^2*ab^2*r^2 + B^2*ab^2*r^2 + C^2*c^2*r^2 - 4] +
+      // m * [- 2*A*ab^2*r + 2*A^2*ab^2*r*q + 2*B^2*ab^2*r*q + 2*C^2*c^2*r*q] +
+      // [ab^2 - 2*A*ab^2*q + A^2*ab^2*q^2 + B^2*ab^2*q^2 + C^2*c^2*q^2]  =  0
+      
+      //System.err.println("    computing X bound");
+      
+      // Useful subexpressions for this bound
+      final double q = A*abSquared*k;
+      final double qSquared = q * q;
+
+      // Quadratic equation
+      final double a = ASquared*abSquared*rSquared + BSquared*abSquared*rSquared + CSquared*cSquared*rSquared - 4.0;
+      final double b = - 2.0*A*abSquared*r + 2.0*ASquared*abSquared*r*q + 2.0*BSquared*abSquared*r*q + 2.0*CSquared*cSquared*r*q;
+      final double c = abSquared - 2.0*A*abSquared*q + ASquared*abSquared*qSquared + BSquared*abSquared*qSquared + CSquared*cSquared*qSquared;
+      
+      if (Math.abs(a) >= MINIMUM_RESOLUTION_SQUARED) {
+        final double sqrtTerm = b*b - 4.0*a*c;
+        if (Math.abs(sqrtTerm) < MINIMUM_RESOLUTION_SQUARED) {
+          // One solution
+          final double m = -b / (2.0 * a);
+          final double l = r * m + q;
+          // x = ((1 - l*A) * ab^2 ) / (2 * m)
+          // y = (-l*B * ab^2) / ( 2 * m)
+          // z = (-l*C * c^2)/ (2 * m)
+          final double denom0 = 0.5 / m;
+          final GeoPoint thePoint = new GeoPoint((1.0-l*A) * abSquared * denom0, -l*B * abSquared * denom0, -l*C * cSquared * denom0);
+          //Math is not quite accurate enough for this
+          //assert planetModel.pointOnSurface(thePoint): "Point: "+thePoint+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
+          //  (thePoint.x*thePoint.x*planetModel.inverseAb*planetModel.inverseAb + thePoint.y*thePoint.y*planetModel.inverseAb*planetModel.inverseAb + thePoint.z*thePoint.z*planetModel.inverseC*planetModel.inverseC);
+          //assert evaluateIsZero(thePoint): "Evaluation of point: "+evaluate(thePoint);
+          addPoint(boundsInfo, bounds, thePoint);
+        } else if (sqrtTerm > 0.0) {
+          // Two solutions
+          final double sqrtResult = Math.sqrt(sqrtTerm);
+          final double commonDenom = 0.5/a;
+          final double m1 = (-b + sqrtResult) * commonDenom;
+          assert Math.abs(a * m1 * m1 + b * m1 + c) < MINIMUM_RESOLUTION;
+          final double m2 = (-b - sqrtResult) * commonDenom;
+          assert Math.abs(a * m2 * m2 + b * m2 + c) < MINIMUM_RESOLUTION;
+          final double l1 = r * m1 + q;
+          final double l2 = r * m2 + q;
+          // x = ((1 - l*A) * ab^2 ) / (2 * m)
+          // y = (-l*B * ab^2) / ( 2 * m)
+          // z = (-l*C * c^2)/ (2 * m)
+          final double denom1 = 0.5 / m1;
+          final double denom2 = 0.5 / m2;
+          final GeoPoint thePoint1 = new GeoPoint((1.0-l1*A) * abSquared * denom1, -l1*B * abSquared * denom1, -l1*C * cSquared * denom1);
+          final GeoPoint thePoint2 = new GeoPoint((1.0-l2*A) * abSquared * denom2, -l2*B * abSquared * denom2, -l2*C * cSquared * denom2);
+          //Math is not quite accurate enough for this
+          //assert planetModel.pointOnSurface(thePoint1): "Point1: "+thePoint1+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
+          //  (thePoint1.x*thePoint1.x*planetModel.inverseAb*planetModel.inverseAb + thePoint1.y*thePoint1.y*planetModel.inverseAb*planetModel.inverseAb + thePoint1.z*thePoint1.z*planetModel.inverseC*planetModel.inverseC);
+          //assert planetModel.pointOnSurface(thePoint2): "Point1: "+thePoint2+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
+          //  (thePoint2.x*thePoint2.x*planetModel.inverseAb*planetModel.inverseAb + thePoint2.y*thePoint2.y*planetModel.inverseAb*planetModel.inverseAb + thePoint2.z*thePoint2.z*planetModel.inverseC*planetModel.inverseC);
+          //assert evaluateIsZero(thePoint1): "Evaluation of point1: "+evaluate(thePoint1);
+          //assert evaluateIsZero(thePoint2): "Evaluation of point2: "+evaluate(thePoint2);
+          addPoint(boundsInfo, bounds, thePoint1);
+          addPoint(boundsInfo, bounds, thePoint2);
+        } else {
+          // No solutions
+        }
+      } else if (Math.abs(b) > MINIMUM_RESOLUTION_SQUARED) {
+        //System.err.println("Not x quadratic");
+        // a = 0, so m = - c / b
+        final double m = -c / b;
+        final double l = r * m + q;
+        // x = ((1 - l*A) * ab^2 ) / (2 * m)
+        // y = (-l*B * ab^2) / ( 2 * m)
+        // z = (-l*C * c^2)/ (2 * m)
+        final double denom0 = 0.5 / m;
+        final GeoPoint thePoint = new GeoPoint((1.0-l*A) * abSquared * denom0, -l*B * abSquared * denom0, -l*C * cSquared * denom0);
+        //Math is not quite accurate enough for this
+        //assert planetModel.pointOnSurface(thePoint): "Point: "+thePoint+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
+        //  (thePoint.x*thePoint.x*planetModel.inverseAb*planetModel.inverseAb + thePoint.y*thePoint.y*planetModel.inverseAb*planetModel.inverseAb + thePoint.z*thePoint.z*planetModel.inverseC*planetModel.inverseC);
+        //assert evaluateIsZero(thePoint): "Evaluation of point: "+evaluate(thePoint);
+        addPoint(boundsInfo, bounds, thePoint);
+      } else {
+        // Something went very wrong; a = b = 0
+      }
+    }
+    
+    // Do Y
+    if (!boundsInfo.isSmallestMinY(planetModel) || !boundsInfo.isLargestMaxY(planetModel)) {
+      // For min/max x, we need to use lagrange multipliers.
+      //
+      // For this, we need grad(F(x,y,z)) = (dF/dx, dF/dy, dF/dz).
+      //
+      // Minimize and maximize f(x,y,z) = y, with respect to g(x,y,z) = Ax + By + Cz - D and h(x,y,z) = x^2/ab^2 + y^2/ab^2 + z^2/c^2 - 1
+      //
+      // grad(f(x,y,z)) = (0,1,0)
+      // grad(g(x,y,z)) = (A,B,C)
+      // grad(h(x,y,z)) = (2x/ab^2,2y/ab^2,2z/c^2)
+      //
+      // Equations we need to simultaneously solve:
+      // 
+      // grad(f(x,y,z)) = l * grad(g(x,y,z)) + m * grad(h(x,y,z))
+      // g(x,y,z) = 0
+      // h(x,y,z) = 0
+      // 
+      // Equations:
+      // 0 = l*A + m*2x/ab^2
+      // 1 = l*B + m*2y/ab^2
+      // 0 = l*C + m*2z/c^2
+      // Ax + By + Cz + D = 0
+      // x^2/ab^2 + y^2/ab^2 + z^2/c^2 - 1 = 0
+      // 
+      // Solve for x,y,z in terms of (l, m):
+      // 
+      // x = (-l*A * ab^2 ) / (2 * m)
+      // y = ((1 - l*B) * ab^2) / ( 2 * m)
+      // z = (-l*C * c^2)/ (2 * m)
+      // 
+      // Two equations, two unknowns:
+      // 
+      // A * ((-l*A * ab^2 ) / (2 * m)) + B * (((1 - l*B) * ab^2) / ( 2 * m)) + C * ((-l*C * c^2)/ (2 * m)) + D = 0
+      // 
+      // and
+      // 
+      // ((-l*A * ab^2 ) / (2 * m))^2/ab^2 + (((1 - l*B) * ab^2) / ( 2 * m))^2/ab^2 + ((-l*C * c^2)/ (2 * m))^2/c^2 - 1 = 0
+      // 
+      // Simple: solve for l and m, then find y from it.
+      // 
+      // (a) Use first equation to find l in terms of m.
+      // 
+      // A * ((-l*A * ab^2 ) / (2 * m)) + B * (((1 - l*B) * ab^2) / ( 2 * m)) + C * ((-l*C * c^2)/ (2 * m)) + D = 0
+      // A * (-l*A * ab^2 ) + B * ((1-l*B) * ab^2) + C * (-l*C * c^2) + D * 2 * m = 0
+      // -A^2*l*ab^2 + B*ab^2 - l*B^2*ab^2 - C^2*l*c^2 + D*2*m = 0
+      // - l *(A^2* ab^2 + B^2 * ab^2 + C^2 * c^2) + (B * ab^2 + D * 2 * m) = 0
+      // l = (B * ab^2 + D * 2 * m) / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2)
+      // l = B * ab^2 / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2) + m * 2 * D / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2)
+      // 
+      // For convenience:
+      // 
+      // k = 1.0 / (A^2* ab^2 + B^2 * ab^2 + C^2 * c^2)
+      // 
+      // Then:
+      // 
+      // l = B * ab^2 * k + m * 2 * D * k
+      // l = k * (B*ab^2 + m*2*D)
+      //
+      // For further convenience:
+      //
+      // q = B*ab^2*k
+      // r = 2*D*k
+      //
+      // l = (r*m + q)
+      // l^2 = (r^2 * m^2 + 2*r*m*q + q^2)
+      // 
+      // (b) Simplify the second equation before substitution
+      // 
+      // ((-l*A * ab^2 ) / (2 * m))^2/ab^2 + (((1 - l*B) * ab^2) / ( 2 * m))^2/ab^2 + ((-l*C * c^2)/ (2 * m))^2/c^2 - 1 = 0
+      // (-l*A * ab^2 )^2/ab^2 + ((1 - l*B) * ab^2)^2/ab^2 + (-l*C * c^2)^2/c^2 = 4 * m^2
+      // (-l*A)^2 * ab^2 + (1 - l*B)^2 * ab^2 + (-l*C)^2 * c^2 = 4 * m^2
+      // l^2*A^2 * ab^2 + (1 - 2*l*B + l^2*B^2) * ab^2 + l^2*C^2 * c^2 = 4 * m^2
+      // A^2*ab^2*l^2 + ab^2 - 2*B*ab^2*l + B^2*ab^2*l^2 + C^2*c^2*l^2 - 4*m^2 = 0
+      // 
+      // (c) Substitute for l, l^2
+      //
+      // A^2*ab^2*(r^2 * m^2 + 2*r*m*q + q^2) + ab^2 - 2*B*ab^2*(r*m + q) + B^2*ab^2*(r^2 * m^2 + 2*r*m*q + q^2) + C^2*c^2*(r^2 * m^2 + 2*r*m*q + q^2) - 4*m^2 = 0
+      // A^2*ab^2*r^2*m^2 + 2*A^2*ab^2*r*q*m + A^2*ab^2*q^2 + ab^2 - 2*B*ab^2*r*m - 2*B*ab^2*q + B^2*ab^2*r^2*m^2 +
+      //    2*B^2*ab^2*r*q*m + B^2*ab^2*q^2 + C^2*c^2*r^2*m^2 + 2*C^2*c^2*r*q*m + C^2*c^2*q^2 - 4*m^2 = 0
+      //
+      // (d) Group
+      //
+      // m^2 * [A^2*ab^2*r^2 + B^2*ab^2*r^2 + C^2*c^2*r^2 - 4] +
+      // m * [2*A^2*ab^2*r*q - 2*B*ab^2*r + 2*B^2*ab^2*r*q + 2*C^2*c^2*r*q] +
+      // [A^2*ab^2*q^2 + ab^2 - 2*B*ab^2*q + B^2*ab^2*q^2 + C^2*c^2*q^2]  =  0
+
+      //System.err.println("    computing Y bound");
+      
+      // Useful subexpressions for this bound
+      final double q = B*abSquared*k;
+      final double qSquared = q * q;
+
+      // Quadratic equation
+      final double a = ASquared*abSquared*rSquared + BSquared*abSquared*rSquared + CSquared*cSquared*rSquared - 4.0;
+      final double b = 2.0*ASquared*abSquared*r*q - 2.0*B*abSquared*r + 2.0*BSquared*abSquared*r*q + 2.0*CSquared*cSquared*r*q;
+      final double c = ASquared*abSquared*qSquared + abSquared - 2.0*B*abSquared*q + BSquared*abSquared*qSquared + CSquared*cSquared*qSquared;
+
+      if (Math.abs(a) >= MINIMUM_RESOLUTION_SQUARED) {
+        final double sqrtTerm = b*b - 4.0*a*c;
+        if (Math.abs(sqrtTerm) < MINIMUM_RESOLUTION_SQUARED) {
+          // One solution
+          final double m = -b / (2.0 * a);
+          final double l = r * m + q;
+          // x = (-l*A * ab^2 ) / (2 * m)
+          // y = ((1.0-l*B) * ab^2) / ( 2 * m)
+          // z = (-l*C * c^2)/ (2 * m)
+          final double denom0 = 0.5 / m;
+          final GeoPoint thePoint = new GeoPoint(-l*A * abSquared * denom0, (1.0-l*B) * abSquared * denom0, -l*C * cSquared * denom0);
+          //Math is not quite accurate enough for this
+          //assert planetModel.pointOnSurface(thePoint): "Point: "+thePoint+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
+          //  (thePoint1.x*thePoint.x*planetModel.inverseAb*planetModel.inverseAb + thePoint.y*thePoint.y*planetModel.inverseAb*planetModel.inverseAb + thePoint.z*thePoint.z*planetModel.inverseC*planetModel.inverseC);
+          //assert evaluateIsZero(thePoint): "Evaluation of point: "+evaluate(thePoint);
+          addPoint(boundsInfo, bounds, thePoint);
+        } else if (sqrtTerm > 0.0) {
+          // Two solutions
+          final double sqrtResult = Math.sqrt(sqrtTerm);
+          final double commonDenom = 0.5/a;
+          final double m1 = (-b + sqrtResult) * commonDenom;
+          assert Math.abs(a * m1 * m1 + b * m1 + c) < MINIMUM_RESOLUTION;
+          final double m2 = (-b - sqrtResult) * commonDenom;
+          assert Math.abs(a * m2 * m2 + b * m2 + c) < MINIMUM_RESOLUTION;
+          final double l1 = r * m1 + q;
+          final double l2 = r * m2 + q;
+          // x = (-l*A * ab^2 ) / (2 * m)
+          // y = ((1.0-l*B) * ab^2) / ( 2 * m)
+          // z = (-l*C * c^2)/ (2 * m)
+          final double denom1 = 0.5 / m1;
+          final double denom2 = 0.5 / m2;
+          final GeoPoint thePoint1 = new GeoPoint(-l1*A * abSquared * denom1, (1.0-l1*B) * abSquared * denom1, -l1*C * cSquared * denom1);
+          final GeoPoint thePoint2 = new GeoPoint(-l2*A * abSquared * denom2, (1.0-l2*B) * abSquared * denom2, -l2*C * cSquared * denom2);
+          //Math is not quite accurate enough for this
+          //assert planetModel.pointOnSurface(thePoint1): "Point1: "+thePoint1+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
+          //  (thePoint1.x*thePoint1.x*planetModel.inverseAb*planetModel.inverseAb + thePoint1.y*thePoint1.y*planetModel.inverseAb*planetModel.inverseAb + thePoint1.z*thePoint1.z*planetModel.inverseC*planetModel.inverseC);
+          //assert planetModel.pointOnSurface(thePoint2): "Point2: "+thePoint2+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
+          //  (thePoint2.x*thePoint2.x*planetModel.inverseAb*planetModel.inverseAb + thePoint2.y*thePoint2.y*planetModel.inverseAb*planetModel.inverseAb + thePoint2.z*thePoint2.z*planetModel.inverseC*planetModel.inverseC);
+          //assert evaluateIsZero(thePoint1): "Evaluation of point1: "+evaluate(thePoint1);
+          //assert evaluateIsZero(thePoint2): "Evaluation of point2: "+evaluate(thePoint2);
+          addPoint(boundsInfo, bounds, thePoint1);
+          addPoint(boundsInfo, bounds, thePoint2);
+        } else {
+          // No solutions
+        }
+      } else if (Math.abs(b) > MINIMUM_RESOLUTION_SQUARED) {
+        // a = 0, so m = - c / b
+        final double m = -c / b;
+        final double l = r * m + q;
+        // x = ( -l*A * ab^2 ) / (2 * m)
+        // y = ((1-l*B) * ab^2) / ( 2 * m)
+        // z = (-l*C * c^2)/ (2 * m)
+        final double denom0 = 0.5 / m;
+        final GeoPoint thePoint = new GeoPoint(-l*A * abSquared * denom0, (1.0-l*B) * abSquared * denom0, -l*C * cSquared * denom0);
+        //Math is not quite accurate enough for this
+        //assert planetModel.pointOnSurface(thePoint): "Point: "+thePoint+"; Planetmodel="+planetModel+"; A="+A+" B="+B+" C="+C+" D="+D+" planetfcn="+
+        //  (thePoint.x*thePoint.x*planetModel.inverseAb*planetModel.inverseAb + thePoint.y*thePoint.y*planetModel.inverseAb*planetModel.inverseAb + thePoint.z*thePoint.z*planetModel.inverseC*planetModel.inverseC);
+        //assert evaluateIsZero(thePoint): "Evaluation of point: "+evaluate(thePoint);
+        addPoint(boundsInfo, bounds, thePoint);
+      } else {
+        // Something went very wrong; a = b = 0
+      }
+    }
+  }
+  
+  /**
+   * Accumulate bounds information for this plane, intersected with the unit sphere.
+   * Updates both latitude and longitude information, using max/min points found
+   * within the specified bounds.
+   *
+   * @param planetModel is the planet model to use in determining bounds.
+   * @param boundsInfo is the lat/lon info to update with additional bounding information.
+   * @param bounds     are the surfaces delineating what's inside the shape.
+   */
+  public void recordBounds(final PlanetModel planetModel, final LatLonBounds boundsInfo, final Membership... bounds) {
+    // For clarity, load local variables with good names
+    final double A = this.x;
+    final double B = this.y;
+    final double C = this.z;
+
+    // Now compute latitude min/max points
+    if (!boundsInfo.checkNoTopLatitudeBound() || !boundsInfo.checkNoBottomLatitudeBound()) {
+      //System.err.println("Looking at latitude for plane "+this);
+      // With ellipsoids, we really have only one viable way to do this computation.
+      // Specifically, we compute an appropriate vertical plane, based on the current plane's x-y orientation, and
+      // then intersect it with this one and with the ellipsoid.  This gives us zero, one, or two points to use
+      // as bounds.
+      // There is one special case: horizontal circles.  These require TWO vertical planes: one for the x, and one for
+      // the y, and we use all four resulting points in the bounds computation.
+      if ((Math.abs(A) >= MINIMUM_RESOLUTION || Math.abs(B) >= MINIMUM_RESOLUTION)) {
+        // NOT a horizontal circle!
+        //System.err.println(" Not a horizontal circle");
+        final Plane verticalPlane = constructNormalizedZPlane(A,B);
+        final GeoPoint[] points = findIntersections(planetModel, verticalPlane, bounds, NO_BOUNDS);
+        for (final GeoPoint point : points) {
+          addPoint(boundsInfo, bounds, point);
+        }
+      } else {
+        // Horizontal circle.  Since a==b, any vertical plane suffices.
+        final GeoPoint[] points = findIntersections(planetModel, normalXPlane, NO_BOUNDS, NO_BOUNDS);
+        boundsInfo.addZValue(points[0]);
+      }
+      //System.err.println("Done latitude bounds");
+    }
+
+    // First, figure out our longitude bounds, unless we no longer need to consider that
+    if (!boundsInfo.checkNoLongitudeBound()) {
+      //System.err.println("Computing longitude bounds for "+this);
+      //System.out.println("A = "+A+" B = "+B+" C = "+C+" D = "+D);
+      // Compute longitude bounds
+
+      double a;
+      double b;
+      double c;
+
+      if (Math.abs(C) < MINIMUM_RESOLUTION) {
+        // Degenerate; the equation describes a line
+        //System.out.println("It's a zero-width ellipse");
+        // Ax + By + D = 0
+        if (Math.abs(D) >= MINIMUM_RESOLUTION) {
+          if (Math.abs(A) > Math.abs(B)) {
+            // Use equation suitable for A != 0
+            // We need to find the endpoints of the zero-width ellipse.
+            // Geometrically, we have a line segment in x-y space.  We need to locate the endpoints
+            // of that line.  But luckily, we know some things: specifically, since it is a
+            // degenerate situation in projection, the C value had to have been 0.  That
+            // means that our line's endpoints will coincide with the projected ellipse.  All we
+            // need to do then is to find the intersection of the projected ellipse and the line
+            // equation:
+            //
+            // A x + B y + D = 0
+            //
+            // Since A != 0:
+            // x = (-By - D)/A
+            //
+            // The projected ellipse:
+            // x^2/a^2 + y^2/b^2 - 1 = 0
+            // Substitute:
+            // [(-By-D)/A]^2/a^2 + y^2/b^2 -1 = 0
+            // Multiply through by A^2:
+            // [-By - D]^2/a^2 + A^2*y^2/b^2 - A^2 = 0
+            // Multiply out:
+            // B^2*y^2/a^2 + 2BDy/a^2 + D^2/a^2 + A^2*y^2/b^2 - A^2 = 0
+            // Group:
+            // y^2 * [B^2/a^2 + A^2/b^2] + y [2BD/a^2] + [D^2/a^2-A^2] = 0
+
+            a = B * B * planetModel.inverseAbSquared + A * A * planetModel.inverseAbSquared;
+            b = 2.0 * B * D * planetModel.inverseAbSquared;
+            c = D * D * planetModel.inverseAbSquared - A * A;
+
+            double sqrtClause = b * b - 4.0 * a * c;
+
+            if (Math.abs(sqrtClause) < MINIMUM_RESOLUTION_SQUARED) {
+              double y0 = -b / (2.0 * a);
+              double x0 = (-D - B * y0) / A;
+              double z0 = 0.0;
+              addPoint(boundsInfo, bounds, new GeoPoint(x0, y0, z0));
+            } else if (sqrtClause > 0.0) {
+              double sqrtResult = Math.sqrt(sqrtClause);
+              double denom = 1.0 / (2.0 * a);
+              double Hdenom = 1.0 / A;
+
+              double y0a = (-b + sqrtResult) * denom;
+              double y0b = (-b - sqrtResult) * denom;
+
+              double x0a = (-D - B * y0a) * Hdenom;
+              double x0b = (-D - B * y0b) * Hdenom;
+
+              double z0a = 0.0;
+              double z0b = 0.0;
+
+              addPoint(boundsInfo, bounds, new GeoPoint(x0a, y0a, z0a));
+              addPoint(boundsInfo, bounds, new GeoPoint(x0b, y0b, z0b));
+            }
+
+          } else {
+            // Use equation suitable for B != 0
+            // Since I != 0, we rewrite:
+            // y = (-Ax - D)/B
+            a = B * B * planetModel.inverseAbSquared + A * A * planetModel.inverseAbSquared;
+            b = 2.0 * A * D * planetModel.inverseAbSquared;
+            c = D * D * planetModel.inverseAbSquared - B * B;
+
+            double sqrtClause = b * b - 4.0 * a * c;
+
+            if (Math.abs(sqrtClause) < MINIMUM_RESOLUTION_SQUARED) {
+              double x0 = -b / (2.0 * a);
+              double y0 = (-D - A * x0) / B;
+              double z0 = 0.0;
+              addPoint(boundsInfo, bounds, new GeoPoint(x0, y0, z0));
+            } else if (sqrtClause > 0.0) {
+              double sqrtResult = Math.sqrt(sqrtClause);
+              double denom = 1.0 / (2.0 * a);
+              double Idenom = 1.0 / B;
+
+              double x0a = (-b + sqrtResult) * denom;
+              double x0b = (-b - sqrtResult) * denom;
+              double y0a = (-D - A * x0a) * Idenom;
+              double y0b = (-D - A * x0b) * Idenom;
+              double z0a = 0.0;
+              double z0b = 0.0;
+
+              addPoint(boundsInfo, bounds, new GeoPoint(x0a, y0a, z0a));
+              addPoint(boundsInfo, bounds, new GeoPoint(x0b, y0b, z0b));
+            }
+          }
+        }
+
+      } else {
+        //System.err.println("General longitude bounds...");
+
+        // NOTE WELL: The x,y,z values generated here are NOT on the unit sphere.
+        // They are for lat/lon calculation purposes only.  x-y is meant to be used for longitude determination,
+        // and z for latitude, and that's all the values are good for.
+
+        // (1) Intersect the plane and the ellipsoid, and project the results into the x-y plane:
+        // From plane:
+        // z = (-Ax - By - D) / C
+        // From ellipsoid:
+        // x^2/a^2 + y^2/b^2 + [(-Ax - By - D) / C]^2/c^2 = 1
+        // Simplify/expand:
+        // C^2*x^2/a^2 + C^2*y^2/b^2 + (-Ax - By - D)^2/c^2 = C^2
+        //
+        // x^2 * C^2/a^2 + y^2 * C^2/b^2 + x^2 * A^2/c^2 + ABxy/c^2 + ADx/c^2 + ABxy/c^2 + y^2 * B^2/c^2 + BDy/c^2 + ADx/c^2 + BDy/c^2 + D^2/c^2 = C^2
+        // Group:
+        // [A^2/c^2 + C^2/a^2] x^2 + [B^2/c^2 + C^2/b^2] y^2 + [2AB/c^2]xy + [2AD/c^2]x + [2BD/c^2]y + [D^2/c^2-C^2] = 0
+        // For convenience, introduce post-projection coefficient variables to make life easier.
+        // E x^2 + F y^2 + G xy + H x + I y + J = 0
+        double E = A * A * planetModel.inverseCSquared + C * C * planetModel.inverseAbSquared;
+        double F = B * B * planetModel.inverseCSquared + C * C * planetModel.inverseAbSquared;
+        double G = 2.0 * A * B * planetModel.inverseCSquared;
+        double H = 2.0 * A * D * planetModel.inverseCSquared;
+        double I = 2.0 * B * D * planetModel.inverseCSquared;
+        double J = D * D * planetModel.inverseCSquared - C * C;
+
+        //System.err.println("E = " + E + " F = " + F + " G = " + G + " H = "+ H + " I = " + I + " J = " + J);
+
+        // Check if the origin is within, by substituting x = 0, y = 0 and seeing if less than zero
+        if (Math.abs(J) >= MINIMUM_RESOLUTION && J > 0.0) {
+          // The derivative of the curve above is:
+          // 2Exdx + 2Fydy + G(xdy+ydx) + Hdx + Idy = 0
+          // (2Ex + Gy + H)dx + (2Fy + Gx + I)dy = 0
+          // dy/dx = - (2Ex + Gy + H) / (2Fy + Gx + I)
+          //
+          // The equation of a line going through the origin with the slope dy/dx is:
+          // y = dy/dx x
+          // y = - (2Ex + Gy + H) / (2Fy + Gx + I)  x
+          // Rearrange:
+          // (2Fy + Gx + I) y + (2Ex + Gy + H) x = 0
+          // 2Fy^2 + Gxy + Iy + 2Ex^2 + Gxy + Hx = 0
+          // 2Ex^2 + 2Fy^2 + 2Gxy + Hx + Iy = 0
+          //
+          // Multiply the original equation by 2:
+          // 2E x^2 + 2F y^2 + 2G xy + 2H x + 2I y + 2J = 0
+          // Subtract one from the other, to remove the high-order terms:
+          // Hx + Iy + 2J = 0
+          // Now, we can substitute either x = or y = into the derivative equation, or into the original equation.
+          // But we will need to base this on which coefficient is non-zero
+
+          if (Math.abs(H) > Math.abs(I)) {
+            //System.err.println(" Using the y quadratic");
+            // x = (-2J - Iy)/H
+
+            // Plug into the original equation:
+            // E [(-2J - Iy)/H]^2 + F y^2 + G [(-2J - Iy)/H]y + H [(-2J - Iy)/H] + I y + J = 0
+            // E [(-2J - Iy)/H]^2 + F y^2 + G [(-2J - Iy)/H]y - J = 0
+            // Same equation as derivative equation, except for a factor of 2!  So it doesn't matter which we pick.
+
+            // Plug into derivative equation:
+            // 2E[(-2J - Iy)/H]^2 + 2Fy^2 + 2G[(-2J - Iy)/H]y + H[(-2J - Iy)/H] + Iy = 0
+            // 2E[(-2J - Iy)/H]^2 + 2Fy^2 + 2G[(-2J - Iy)/H]y - 2J = 0
+            // E[(-2J - Iy)/H]^2 + Fy^2 + G[(-2J - Iy)/H]y - J = 0
+
+            // Multiply by H^2 to make manipulation easier
+            // E[(-2J - Iy)]^2 + F*H^2*y^2 + GH[(-2J - Iy)]y - J*H^2 = 0
+            // Do the square
+            // E[4J^2 + 4IJy + I^2*y^2] + F*H^2*y^2 + GH(-2Jy - I*y^2) - J*H^2 = 0
+
+            // Multiply it out
+            // 4E*J^2 + 4EIJy + E*I^2*y^2 + H^2*Fy^2 - 2GHJy - GH*I*y^2 - J*H^2 = 0
+            // Group:
+            // y^2 [E*I^2 - GH*I + F*H^2] + y [4EIJ - 2GHJ] + [4E*J^2 - J*H^2] = 0
+
+            a = E * I * I - G * H * I + F * H * H;
+            b = 4.0 * E * I * J - 2.0 * G * H * J;
+            c = 4.0 * E * J * J - J * H * H;
+
+            //System.out.println("a="+a+" b="+b+" c="+c);
+            double sqrtClause = b * b - 4.0 * a * c;
+            //System.out.println("sqrtClause="+sqrtClause);
+
+            if (Math.abs(sqrtClause) < MINIMUM_RESOLUTION_CUBED) {
+              //System.err.println(" One solution");
+              double y0 = -b / (2.0 * a);
+              double x0 = (-2.0 * J - I * y0) / H;
+              double z0 = (-A * x0 - B * y0 - D) / C;
+
+              addPoint(boundsInfo, bounds, new GeoPoint(x0, y0, z0));
+            } else if (sqrtClause > 0.0) {
+              //System.err.println(" Two solutions");
+              double sqrtResult = Math.sqrt(sqrtClause);
+              double denom = 1.0 / (2.0 * a);
+              double Hdenom = 1.0 / H;
+              double Cdenom = 1.0 / C;
+
+              double y0a = (-b + sqrtResult) * denom;
+              double y0b = (-b - sqrtResult) * denom;
+              double x0a = (-2.0 * J - I * y0a) * Hdenom;
+              double x0b = (-2.0 * J - I * y0b) * Hdenom;
+              double z0a = (-A * x0a - B * y0a - D) * Cdenom;
+              double z0b = (-A * x0b - B * y0b - D) * Cdenom;
+
+              addPoint(boundsInfo, bounds, new GeoPoint(x0a, y0a, z0a));
+              addPoint(boundsInfo, bounds, new GeoPoint(x0b, y0b, z0b));
+            }
+
+          } else {
+            //System.err.println(" Using the x quadratic");
+            // y = (-2J - Hx)/I
+
+            // Plug into the original equation:
+            // E x^2 + F [(-2J - Hx)/I]^2 + G x[(-2J - Hx)/I] - J = 0
+
+            // Multiply by I^2 to make manipulation easier
+            // E * I^2 * x^2 + F [(-2J - Hx)]^2 + GIx[(-2J - Hx)] - J * I^2 = 0
+            // Do the square
+            // E * I^2 * x^2 + F [ 4J^2 + 4JHx + H^2*x^2] + GI[(-2Jx - H*x^2)] - J * I^2 = 0
+
+            // Multiply it out
+            // E * I^2 * x^2 + 4FJ^2 + 4FJHx + F*H^2*x^2 - 2GIJx - HGI*x^2 - J * I^2 = 0
+            // Group:
+            // x^2 [E*I^2 - GHI + F*H^2] + x [4FJH - 2GIJ] + [4FJ^2 - J*I^2] = 0
+
+            // E x^2 + F y^2 + G xy + H x + I y + J = 0
+
+            a = E * I * I - G * H * I + F * H * H;
+            b = 4.0 * F * H * J - 2.0 * G * I * J;
+            c = 4.0 * F * J * J - J * I * I;
+
+            //System.out.println("a="+a+" b="+b+" c="+c);
+            double sqrtClause = b * b - 4.0 * a * c;
+            //System.out.println("sqrtClause="+sqrtClause);
+            if (Math.abs(sqrtClause) < MINIMUM_RESOLUTION_CUBED) {
+              //System.err.println(" One solution; sqrt clause was "+sqrtClause);
+              double x0 = -b / (2.0 * a);
+              double y0 = (-2.0 * J - H * x0) / I;
+              double z0 = (-A * x0 - B * y0 - D) / C;
+              // Verify that x&y fulfill the equation
+              // 2Ex^2 + 2Fy^2 + 2Gxy + Hx + Iy = 0
+              addPoint(boundsInfo, bounds, new GeoPoint(x0, y0, z0));
+            } else if (sqrtClause > 0.0) {
+              //System.err.println(" Two solutions");
+              double sqrtResult = Math.sqrt(sqrtClause);
+              double denom = 1.0 / (2.0 * a);
+              double Idenom = 1.0 / I;
+              double Cdenom = 1.0 / C;
+
+              double x0a = (-b + sqrtResult) * denom;
+              double x0b = (-b - sqrtResult) * denom;
+              double y0a = (-2.0 * J - H * x0a) * Idenom;
+              double y0b = (-2.0 * J - H * x0b) * Idenom;
+              double z0a = (-A * x0a - B * y0a - D) * Cdenom;
+              double z0b = (-A * x0b - B * y0b - D) * Cdenom;
+
+              addPoint(boundsInfo, bounds, new GeoPoint(x0a, y0a, z0a));
+              addPoint(boundsInfo, bounds, new GeoPoint(x0b, y0b, z0b));
+            }
+          }
+        }
+      }
+    }
+
+  }
+
+  /** Add a point to boundsInfo if within a specifically bounded area.
+   * @param boundsInfo is the object to be modified.
+   * @param bounds is the area that the point must be within.
+   * @param point is the point.
+   */
+  protected static void addPoint(final Bounds boundsInfo, final Membership[] bounds, final GeoPoint point) {
+    // Make sure the discovered point is within the bounds
+    for (Membership bound : bounds) {
+      if (!bound.isWithin(point))
+        return;
+    }
+    // Add the point
+    boundsInfo.addPoint(point);
+  }
+
+  /** Add a point to boundsInfo if within a specifically bounded area.
+   * @param boundsInfo is the object to be modified.
+   * @param bounds is the area that the point must be within.
+   * @param x is the x value.
+   * @param y is the y value.
+   * @param z is the z value.
+   */
+  /*
+  protected static void addPoint(final Bounds boundsInfo, final Membership[] bounds, final double x, final double y, final double z) {
+    //System.err.println(" Want to add point x="+x+" y="+y+" z="+z);
+    // Make sure the discovered point is within the bounds
+    for (Membership bound : bounds) {
+      if (!bound.isWithin(x, y, z))
+        return;
+    }
+    // Add the point
+    //System.err.println("  point added");
+    //System.out.println("Adding point x="+x+" y="+y+" z="+z);
+    boundsInfo.addPoint(x, y, z);
+  }
+  */
+
+  /**
+   * Determine whether the plane intersects another plane within the
+   * bounds provided.
+   *
+   * @param planetModel is the planet model to use in determining intersection.
+   * @param q                 is the other plane.
+   * @param notablePoints     are points to look at to disambiguate cases when the two planes are identical.
+   * @param moreNotablePoints are additional points to look at to disambiguate cases when the two planes are identical.
+   * @param bounds            is one part of the bounds.
+   * @param moreBounds        are more bounds.
+   * @return true if there's an intersection.
+   */
+  public boolean intersects(final PlanetModel planetModel, final Plane q, final GeoPoint[] notablePoints, final GeoPoint[] moreNotablePoints, final Membership[] bounds, final Membership... moreBounds) {
+    //System.err.println("Does plane "+this+" intersect with plane "+q);
+    // If the two planes are identical, then the math will find no points of intersection.
+    // So a special case of this is to check for plane equality.  But that is not enough, because
+    // what we really need at that point is to determine whether overlap occurs between the two parts of the intersection
+    // of plane and circle.  That is, are there *any* points on the plane that are within the bounds described?
+    if (isNumericallyIdentical(q)) {
+      //System.err.println(" Identical plane");
+      // The only way to efficiently figure this out will be to have a list of trial points available to evaluate.
+      // We look for any point that fulfills all the bounds.
+      for (GeoPoint p : notablePoints) {
+        if (meetsAllBounds(p, bounds, moreBounds)) {
+          //System.err.println("  found a notable point in bounds, so intersects");
+          return true;
+        }
+      }
+      for (GeoPoint p : moreNotablePoints) {
+        if (meetsAllBounds(p, bounds, moreBounds)) {
+          //System.err.println("  found a notable point in bounds, so intersects");
+          return true;
+        }
+      }
+      //System.err.println("  no notable points inside found; no intersection");
+      return false;
+    }
+    return findIntersections(planetModel, q, bounds, moreBounds).length > 0;
+  }
+
+  /**
+   * Returns true if this plane and the other plane are identical within the margin of error.
+   * @param p is the plane to compare against.
+   * @return true if the planes are numerically identical.
+   */
+  protected boolean isNumericallyIdentical(final Plane p) {
+    // We can get the correlation by just doing a parallel plane check.  If that passes, then compute a point on the plane
+    // (using D) and see if it also on the other plane.
+    if (Math.abs(this.y * p.z - this.z * p.y) >= MINIMUM_RESOLUTION)
+      return false;
+    if (Math.abs(this.z * p.x - this.x * p.z) >= MINIMUM_RESOLUTION)
+      return false;
+    if (Math.abs(this.x * p.y - this.y * p.x) >= MINIMUM_RESOLUTION)
+      return false;
+
+    // Now, see whether the parallel planes are in fact on top of one another.
+    // The math:
+    // We need a single point that fulfills:
+    // Ax + By + Cz + D = 0
+    // Pick:
+    // x0 = -(A * D) / (A^2 + B^2 + C^2)
+    // y0 = -(B * D) / (A^2 + B^2 + C^2)
+    // z0 = -(C * D) / (A^2 + B^2 + C^2)
+    // Check:
+    // A (x0) + B (y0) + C (z0) + D =? 0
+    // A (-(A * D) / (A^2 + B^2 + C^2)) + B (-(B * D) / (A^2 + B^2 + C^2)) + C (-(C * D) / (A^2 + B^2 + C^2)) + D ?= 0
+    // -D [ A^2 / (A^2 + B^2 + C^2) + B^2 / (A^2 + B^2 + C^2) + C^2 / (A^2 + B^2 + C^2)] + D ?= 0
+    // Yes.
+    final double denom = 1.0 / (p.x * p.x + p.y * p.y + p.z * p.z);
+    return evaluateIsZero(-p.x * p.D * denom, -p.y * p.D * denom, -p.z * p.D * denom);
+  }
+
+  /**
+   * Check if a vector meets the provided bounds.
+   * @param p is the vector.
+   * @param bounds are the bounds.
+   * @return true if the vector describes a point within the bounds.
+   */
+  protected static boolean meetsAllBounds(final Vector p, final Membership[] bounds) {
+    return meetsAllBounds(p.x, p.y, p.z, bounds);
+  }
+
+  /**
+   * Check if a vector meets the provided bounds.
+   * @param x is the x value.
+   * @param y is the y value.
+   * @param z is the z value.
+   * @param bounds are the bounds.
+   * @return true if the vector describes a point within the bounds.
+   */
+  protected static boolean meetsAllBounds(final double x, final double y, final double z, final Membership[] bounds) {
+    for (final Membership bound : bounds) {
+      if (!bound.isWithin(x,y,z))
+        return false;
+    }
+    return true;
+  }
+
+  /**
+   * Check if a vector meets the provided bounds.
+   * @param p is the vector.
+   * @param bounds are the bounds.
+   * @param moreBounds are an additional set of bounds.
+   * @return true if the vector describes a point within the bounds.
+   */
+  protected static boolean meetsAllBounds(final Vector p, final Membership[] bounds, final Membership[] moreBounds) {
+    return meetsAllBounds(p.x, p.y, p.z, bounds, moreBounds);
+  }
+
+  /**
+   * Check if a vector meets the provided bounds.
+   * @param x is the x value.
+   * @param y is the y value.
+   * @param z is the z value.
+   * @param bounds are the bounds.
+   * @param moreBounds are an additional set of bounds.
+   * @return true if the vector describes a point within the bounds.
+   */
+  protected static boolean meetsAllBounds(final double x, final double y, final double z, final Membership[] bounds,
+                                          final Membership[] moreBounds) {
+    return meetsAllBounds(x,y,z, bounds) && meetsAllBounds(x,y,z, moreBounds);
+  }
+
+  /**
+   * Find a sample point on the intersection between two planes and the world.
+   * @param planetModel is the planet model.
+   * @param q is the second plane to consider.
+   * @return a sample point that is on the intersection between the two planes and the world.
+   */
+  public GeoPoint getSampleIntersectionPoint(final PlanetModel planetModel, final Plane q) {
+    final GeoPoint[] intersections = findIntersections(planetModel, q, NO_BOUNDS, NO_BOUNDS);
+    if (intersections.length == 0)
+      return null;
+    return intersections[0];
+  }
+
+  @Override
+  public String toString() {
+    return "[A=" + x + ", B=" + y + "; C=" + z + "; D=" + D + "]";
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!super.equals(o))
+      return false;
+    if (!(o instanceof Plane))
+      return false;
+    Plane other = (Plane) o;
+    return other.D == D;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    long temp;
+    temp = Double.doubleToLongBits(D);
+    result = 31 * result + (int) (temp ^ (temp >>> 32));
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/PlanetModel.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/PlanetModel.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/PlanetModel.java
new file mode 100644
index 0000000..d45d776
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/PlanetModel.java
@@ -0,0 +1,277 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Holds mathematical constants associated with the model of a planet.
+ * @lucene.experimental
+ */
+public class PlanetModel {
+  
+  /** Planet model corresponding to sphere. */
+  public static final PlanetModel SPHERE = new PlanetModel(1.0,1.0);
+
+  /** Mean radius */
+  public static final double WGS84_MEAN = 6371009.0;
+  /** Polar radius */
+  public static final double WGS84_POLAR = 6356752.314245;
+  /** Equatorial radius */
+  public static final double WGS84_EQUATORIAL = 6378137.0;
+  /** Planet model corresponding to WGS84 */
+  public static final PlanetModel WGS84 = new PlanetModel(WGS84_EQUATORIAL/WGS84_MEAN,
+    WGS84_POLAR/WGS84_MEAN);
+
+  // Surface of the planet:
+  // x^2/a^2 + y^2/b^2 + z^2/c^2 = 1.0
+  // Scaling factors are a,b,c.  geo3d can only support models where a==b, so use ab instead.
+  
+  /** The x/y scaling factor */
+  public final double ab;
+  /** The z scaling factor */
+  public final double c;
+  /** The inverse of ab */
+  public final double inverseAb;
+  /** The inverse of c */
+  public final double inverseC;
+  /** The square of the inverse of ab */
+  public final double inverseAbSquared;
+  /** The square of the inverse of c */
+  public final double inverseCSquared;
+  /** The flattening value */
+  public final double flattening;
+  /** The square ratio */
+  public final double squareRatio;
+  
+  // We do NOT include radius, because all computations in geo3d are in radians, not meters.
+  
+  // Compute north and south pole for planet model, since these are commonly used.
+  
+  /** North pole */
+  public final GeoPoint NORTH_POLE;
+  /** South pole */
+  public final GeoPoint SOUTH_POLE;
+  /** Min X pole */
+  public final GeoPoint MIN_X_POLE;
+  /** Max X pole */
+  public final GeoPoint MAX_X_POLE;
+  /** Min Y pole */
+  public final GeoPoint MIN_Y_POLE;
+  /** Max Y pole */
+  public final GeoPoint MAX_Y_POLE;
+  
+  /** Constructor.
+   * @param ab is the x/y scaling factor.
+   * @param c is the z scaling factor.
+   */
+  public PlanetModel(final double ab, final double c) {
+    this.ab = ab;
+    this.c = c;
+    this.inverseAb = 1.0 / ab;
+    this.inverseC = 1.0 / c;
+    this.flattening = (ab - c) * inverseAb;
+    this.squareRatio = (ab * ab - c * c) / (c * c);
+    this.inverseAbSquared = inverseAb * inverseAb;
+    this.inverseCSquared = inverseC * inverseC;
+    this.NORTH_POLE = new GeoPoint(c, 0.0, 0.0, 1.0, Math.PI * 0.5, 0.0);
+    this.SOUTH_POLE = new GeoPoint(c, 0.0, 0.0, -1.0, -Math.PI * 0.5, 0.0);
+    this.MIN_X_POLE = new GeoPoint(ab, -1.0, 0.0, 0.0, 0.0, -Math.PI);
+    this.MAX_X_POLE = new GeoPoint(ab, 1.0, 0.0, 0.0, 0.0, 0.0);
+    this.MIN_Y_POLE = new GeoPoint(ab, 0.0, -1.0, 0.0, 0.0, -Math.PI * 0.5);
+    this.MAX_Y_POLE = new GeoPoint(ab, 0.0, 1.0, 0.0, 0.0, Math.PI * 0.5);
+  }
+  
+  /** Find the minimum magnitude of all points on the ellipsoid.
+   * @return the minimum magnitude for the planet.
+   */
+  public double getMinimumMagnitude() {
+    return Math.min(this.ab, this.c);
+  }
+
+  /** Find the maximum magnitude of all points on the ellipsoid.
+   * @return the maximum magnitude for the planet.
+   */
+  public double getMaximumMagnitude() {
+    return Math.max(this.ab, this.c);
+  }
+  
+  /** Find the minimum x value.
+   *@return the minimum X value.
+   */
+  public double getMinimumXValue() {
+    return -this.ab;
+  }
+  
+  /** Find the maximum x value.
+   *@return the maximum X value.
+   */
+  public double getMaximumXValue() {
+    return this.ab;
+  }
+
+  /** Find the minimum y value.
+   *@return the minimum Y value.
+   */
+  public double getMinimumYValue() {
+    return -this.ab;
+  }
+  
+  /** Find the maximum y value.
+   *@return the maximum Y value.
+   */
+  public double getMaximumYValue() {
+    return this.ab;
+  }
+  
+  /** Find the minimum z value.
+   *@return the minimum Z value.
+   */
+  public double getMinimumZValue() {
+    return -this.c;
+  }
+  
+  /** Find the maximum z value.
+   *@return the maximum Z value.
+   */
+  public double getMaximumZValue() {
+    return this.c;
+  }
+
+  /** Check if point is on surface.
+   * @param v is the point to check.
+   * @return true if the point is on the planet surface.
+   */
+  public boolean pointOnSurface(final Vector v) {
+    return pointOnSurface(v.x, v.y, v.z);
+  }
+  
+  /** Check if point is on surface.
+   * @param x is the x coord.
+   * @param y is the y coord.
+   * @param z is the z coord.
+   */
+  public boolean pointOnSurface(final double x, final double y, final double z) {
+    // Equation of planet surface is:
+    // x^2 / a^2 + y^2 / b^2 + z^2 / c^2 - 1 = 0
+    return Math.abs(x * x * inverseAb * inverseAb + y * y * inverseAb * inverseAb + z * z * inverseC * inverseC - 1.0) < Vector.MINIMUM_RESOLUTION;
+  }
+
+  /** Check if point is outside surface.
+   * @param v is the point to check.
+   * @return true if the point is outside the planet surface.
+   */
+  public boolean pointOutside(final Vector v) {
+    return pointOutside(v.x, v.y, v.z);
+  }
+  
+  /** Check if point is outside surface.
+   * @param x is the x coord.
+   * @param y is the y coord.
+   * @param z is the z coord.
+   */
+  public boolean pointOutside(final double x, final double y, final double z) {
+    // Equation of planet surface is:
+    // x^2 / a^2 + y^2 / b^2 + z^2 / c^2 - 1 = 0
+    return (x * x + y * y) * inverseAb * inverseAb + z * z * inverseC * inverseC - 1.0 > Vector.MINIMUM_RESOLUTION;
+  }
+  
+  /** Compute surface distance between two points.
+   * @param p1 is the first point.
+   * @param p2 is the second point.
+   * @return the adjusted angle, when multiplied by the mean earth radius, yields a surface distance.  This will differ
+   * from GeoPoint.arcDistance() only when the planet model is not a sphere. @see {@link GeoPoint#arcDistance(GeoPoint)}
+   */
+  public double surfaceDistance(final GeoPoint p1, final GeoPoint p2) {
+    final double latA = p1.getLatitude();
+    final double lonA = p1.getLongitude();
+    final double latB = p2.getLatitude();
+    final double lonB = p2.getLongitude();
+
+    final double L = lonB - lonA;
+    final double oF = 1.0 - this.flattening;
+    final double U1 = Math.atan(oF * Math.tan(latA));
+    final double U2 = Math.atan(oF * Math.tan(latB));
+    final double sU1 = Math.sin(U1);
+    final double cU1 = Math.cos(U1);
+    final double sU2 = Math.sin(U2);
+    final double cU2 = Math.cos(U2);
+
+    double sigma, sinSigma, cosSigma;
+    double cos2Alpha, cos2SigmaM;
+    
+    double lambda = L;
+    double iters = 100;
+
+    do {
+      final double sinLambda = Math.sin(lambda);
+      final double cosLambda = Math.cos(lambda);
+      sinSigma = Math.sqrt((cU2 * sinLambda) * (cU2 * sinLambda) + (cU1 * sU2 - sU1 * cU2 * cosLambda)
+          * (cU1 * sU2 - sU1 * cU2 * cosLambda));
+      if (Math.abs(sinSigma) < Vector.MINIMUM_RESOLUTION)
+        return 0.0;
+
+      cosSigma = sU1 * sU2 + cU1 * cU2 * cosLambda;
+      sigma = Math.atan2(sinSigma, cosSigma);
+      final double sinAlpha = cU1 * cU2 * sinLambda / sinSigma;
+      cos2Alpha = 1.0 - sinAlpha * sinAlpha;
+      cos2SigmaM = cosSigma - 2.0 * sU1 * sU2 / cos2Alpha;
+
+      final double c = this.flattening * 0.625 * cos2Alpha * (4.0 + this.flattening * (4.0 - 3.0 * cos2Alpha));
+      final double lambdaP = lambda;
+      lambda = L + (1.0 - c) * this.flattening * sinAlpha * (sigma + c * sinSigma * (cos2SigmaM + c * cosSigma *
+          (-1.0 + 2.0 * cos2SigmaM * cos2SigmaM)));
+      if (Math.abs(lambda - lambdaP) < Vector.MINIMUM_RESOLUTION)
+        break;
+    } while (--iters > 0);
+
+    if (iters == 0)
+      return 0.0;
+
+    final double uSq = cos2Alpha * this.squareRatio;
+    final double A = 1.0 + uSq * 0.00006103515625 * (4096.0 + uSq * (-768.0 + uSq * (320.0 - 175.0 * uSq)));
+    final double B = uSq * 0.0009765625 * (256.0 + uSq * (-128.0 + uSq * (74.0 - 47.0 * uSq)));
+    final double deltaSigma = B * sinSigma * (cos2SigmaM + B * 0.25 * (cosSigma * (-1.0 + 2.0 * cos2SigmaM * cos2SigmaM) - B * 0.16666666666666666666667 * cos2SigmaM
+            * (-3.0 + 4.0 * sinSigma * sinSigma) * (-3.0 + 4.0 * cos2SigmaM * cos2SigmaM)));
+
+    return this.c * A * (sigma - deltaSigma);
+  }
+
+  @Override
+  public boolean equals(final Object o) {
+    if (!(o instanceof PlanetModel))
+      return false;
+    final PlanetModel other = (PlanetModel)o;
+    return ab == other.ab && c == other.c;
+  }
+  
+  @Override
+  public int hashCode() {
+    return Double.hashCode(ab) + Double.hashCode(c);
+  }
+  
+  @Override
+  public String toString() {
+    if (this.equals(SPHERE)) {
+      return "PlanetModel.SPHERE";
+    } else if (this.equals(WGS84)) {
+      return "PlanetModel.WGS84";
+    } else {
+      return "PlanetModel(ab="+ab+" c="+c+")";
+    }
+  }
+}
+
+


[27/50] [abbrv] lucene-solr git commit: LUCENE-7076: Improve MIGRATE.txt/Point javadocs

Posted by no...@apache.org.
LUCENE-7076: Improve MIGRATE.txt/Point javadocs


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

Branch: refs/heads/apiv2
Commit: 5bb072d4b91b1324cae4ec08a6f24b63078c37af
Parents: 406a163
Author: Robert Muir <rm...@apache.org>
Authored: Tue Mar 8 06:20:25 2016 -0500
Committer: Robert Muir <rm...@apache.org>
Committed: Tue Mar 8 06:21:07 2016 -0500

----------------------------------------------------------------------
 lucene/MIGRATE.txt                              | 14 ++---
 .../org/apache/lucene/document/BinaryPoint.java |  2 +
 .../org/apache/lucene/document/DoublePoint.java |  2 +
 .../org/apache/lucene/document/FloatPoint.java  |  2 +
 .../org/apache/lucene/document/IntPoint.java    |  2 +
 .../org/apache/lucene/document/LongPoint.java   |  2 +
 .../org/apache/lucene/index/PointValues.java    | 54 ++++++++++++++++++--
 .../apache/lucene/search/PointInSetQuery.java   | 13 +----
 .../apache/lucene/search/PointRangeQuery.java   | 11 +---
 .../apache/lucene/document/BigIntegerPoint.java |  2 +
 .../lucene/document/InetAddressPoint.java       |  2 +
 .../org/apache/lucene/document/LatLonPoint.java |  2 +
 .../org/apache/lucene/spatial3d/Geo3DPoint.java |  3 +-
 13 files changed, 79 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5bb072d4/lucene/MIGRATE.txt
----------------------------------------------------------------------
diff --git a/lucene/MIGRATE.txt b/lucene/MIGRATE.txt
index b8d12ac..f931aea 100644
--- a/lucene/MIGRATE.txt
+++ b/lucene/MIGRATE.txt
@@ -74,10 +74,12 @@ would be equivalent to the following code with the old setBoost API:
   float boost = ...;
   q.setBoost(q.getBoost() * boost);
 
-## DimensionalValues replaces NumericField (LUCENE-6917)
+# PointValues replaces NumericField (LUCENE-6917)
 
-DimensionalValues provides faster indexing and searching, a smaller
-index size, and less heap used at search time.  The numeric fields
-(IntField, FloatField, LongField, DoubleField) and NumericRangeQuery
-have been moved to the backward-codecs module and prefixed with
-Legacy.
+PointValues provides faster indexing and searching, a smaller
+index size, and less heap used at search time. See org.apache.lucene.index.PointValues
+for an introduction. 
+
+Legacy numeric encodings from previous versions of Lucene are
+deprecated as LegacyIntField, LegacyFloatField, LegacyLongField, and LegacyDoubleField,
+and can be searched with LegacyNumericRangeQuery.

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5bb072d4/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java b/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java
index e139a87..4e27d81 100644
--- a/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java
+++ b/lucene/core/src/java/org/apache/lucene/document/BinaryPoint.java
@@ -19,6 +19,7 @@ package org.apache.lucene.document;
 import java.util.Arrays;
 import java.util.Comparator;
 
+import org.apache.lucene.index.PointValues;
 import org.apache.lucene.search.MatchNoDocsQuery;
 import org.apache.lucene.search.PointInSetQuery;
 import org.apache.lucene.search.PointRangeQuery;
@@ -40,6 +41,7 @@ import org.apache.lucene.util.StringHelper;
  *   <li>{@link #newRangeQuery(String, byte[], byte[])} for matching a 1D range.
  *   <li>{@link #newRangeQuery(String, byte[][], byte[][])} for matching points/ranges in n-dimensional space.
  * </ul> 
+ * @see PointValues
  */
 public final class BinaryPoint extends Field {
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5bb072d4/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java b/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java
index 52b039f..26ac0ce 100644
--- a/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java
+++ b/lucene/core/src/java/org/apache/lucene/document/DoublePoint.java
@@ -18,6 +18,7 @@ package org.apache.lucene.document;
 
 import java.util.Arrays;
 
+import org.apache.lucene.index.PointValues;
 import org.apache.lucene.search.PointInSetQuery;
 import org.apache.lucene.search.PointRangeQuery;
 import org.apache.lucene.search.Query;
@@ -38,6 +39,7 @@ import org.apache.lucene.util.NumericUtils;
  *   <li>{@link #newRangeQuery(String, double, double)} for matching a 1D range.
  *   <li>{@link #newRangeQuery(String, double[], double[])} for matching points/ranges in n-dimensional space.
  * </ul> 
+ * @see PointValues
  */
 public final class DoublePoint extends Field {
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5bb072d4/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java b/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java
index cad666c..c58881e 100644
--- a/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java
+++ b/lucene/core/src/java/org/apache/lucene/document/FloatPoint.java
@@ -18,6 +18,7 @@ package org.apache.lucene.document;
 
 import java.util.Arrays;
 
+import org.apache.lucene.index.PointValues;
 import org.apache.lucene.search.PointInSetQuery;
 import org.apache.lucene.search.PointRangeQuery;
 import org.apache.lucene.search.Query;
@@ -38,6 +39,7 @@ import org.apache.lucene.util.NumericUtils;
  *   <li>{@link #newRangeQuery(String, float, float)} for matching a 1D range.
  *   <li>{@link #newRangeQuery(String, float[], float[])} for matching points/ranges in n-dimensional space.
  * </ul>
+ * @see PointValues
  */
 public final class FloatPoint extends Field {
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5bb072d4/lucene/core/src/java/org/apache/lucene/document/IntPoint.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/IntPoint.java b/lucene/core/src/java/org/apache/lucene/document/IntPoint.java
index b6f5ae7..cb8315f 100644
--- a/lucene/core/src/java/org/apache/lucene/document/IntPoint.java
+++ b/lucene/core/src/java/org/apache/lucene/document/IntPoint.java
@@ -18,6 +18,7 @@ package org.apache.lucene.document;
 
 import java.util.Arrays;
 
+import org.apache.lucene.index.PointValues;
 import org.apache.lucene.search.PointInSetQuery;
 import org.apache.lucene.search.PointRangeQuery;
 import org.apache.lucene.search.Query;
@@ -38,6 +39,7 @@ import org.apache.lucene.util.NumericUtils;
  *   <li>{@link #newRangeQuery(String, int, int)} for matching a 1D range.
  *   <li>{@link #newRangeQuery(String, int[], int[])} for matching points/ranges in n-dimensional space.
  * </ul>
+ * @see PointValues
  */
 public final class IntPoint extends Field {
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5bb072d4/lucene/core/src/java/org/apache/lucene/document/LongPoint.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/LongPoint.java b/lucene/core/src/java/org/apache/lucene/document/LongPoint.java
index c0672ae..ff78132 100644
--- a/lucene/core/src/java/org/apache/lucene/document/LongPoint.java
+++ b/lucene/core/src/java/org/apache/lucene/document/LongPoint.java
@@ -18,6 +18,7 @@ package org.apache.lucene.document;
 
 import java.util.Arrays;
 
+import org.apache.lucene.index.PointValues;
 import org.apache.lucene.search.PointInSetQuery;
 import org.apache.lucene.search.PointRangeQuery;
 import org.apache.lucene.search.Query;
@@ -38,6 +39,7 @@ import org.apache.lucene.util.NumericUtils;
  *   <li>{@link #newRangeQuery(String, long, long)} for matching a 1D range.
  *   <li>{@link #newRangeQuery(String, long[], long[])} for matching points/ranges in n-dimensional space.
  * </ul>
+ * @see PointValues
  */
 public final class LongPoint extends Field {
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5bb072d4/lucene/core/src/java/org/apache/lucene/index/PointValues.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/PointValues.java b/lucene/core/src/java/org/apache/lucene/index/PointValues.java
index 230a14f..1fb2654 100644
--- a/lucene/core/src/java/org/apache/lucene/index/PointValues.java
+++ b/lucene/core/src/java/org/apache/lucene/index/PointValues.java
@@ -17,17 +17,65 @@
 package org.apache.lucene.index;
 
 import java.io.IOException;
+import java.math.BigInteger;
+import java.net.InetAddress;
 
 import org.apache.lucene.document.BinaryPoint;
 import org.apache.lucene.document.DoublePoint;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.FloatPoint;
 import org.apache.lucene.document.IntPoint;
 import org.apache.lucene.document.LongPoint;
 import org.apache.lucene.util.bkd.BKDWriter;
 
-/** Allows recursively visiting point values indexed with {@link IntPoint},
- *  {@link FloatPoint}, {@link LongPoint}, {@link DoublePoint}
- *  or {@link BinaryPoint}.
+/** 
+ * Access to indexed numeric values.
+ * <p>
+ * Points represent numeric values and are indexed differently than ordinary text. Instead of an inverted index, 
+ * points are indexed with datastructures such as <a href="https://en.wikipedia.org/wiki/K-d_tree">KD-trees</a>. 
+ * These structures are optimized for operations such as <i>range</i>, <i>distance</i>, <i>nearest-neighbor</i>, 
+ * and <i>point-in-polygon</i> queries. 
+ * <h1>Basic Point Types</h1>
+ * <table summary="Basic point types in Java and Lucene">
+ *   <tr><th>Java type</th><th>Lucene class</th></tr>
+ *   <tr><td>{@code int}</td><td>{@link IntPoint}</td></tr>
+ *   <tr><td>{@code long}</td><td>{@link LongPoint}</td></tr>
+ *   <tr><td>{@code float}</td><td>{@link FloatPoint}</td></tr>
+ *   <tr><td>{@code double}</td><td>{@link DoublePoint}</td></tr>
+ *   <tr><td>{@code byte[]}</td><td>{@link BinaryPoint}</td></tr>
+ *   <tr><td>{@link BigInteger}</td><td><a href="{@docRoot}/../sandbox/org/apache/lucene/document/BigIntegerPoint.html">BigIntegerPoint</a>*</td></tr>
+ *   <tr><td>{@link InetAddress}</td><td><a href="{@docRoot}/../sandbox/org/apache/lucene/document/InetAddressPoint.html">InetAddressPoint</a>*</td></tr>
+ * </table>
+ * * in the <i>lucene-sandbox</i> jar<br>
+ * <p>
+ * Basic Lucene point types behave like their java peers: for example {@link IntPoint} represents a signed 32-bit 
+ * {@link Integer}, supporting values ranging from {@link Integer#MIN_VALUE} to {@link Integer#MAX_VALUE}, ordered
+ * consistent with {@link Integer#compareTo(Integer)}. In addition to indexing support, point classes also contain 
+ * static methods (such as {@link IntPoint#newRangeQuery(String, int, int)}) for creating common queries. For example:
+ * <pre class="prettyprint">
+ *   // add year 1970 to document
+ *   document.add(new IntPoint("year", 1970));
+ *   // index document
+ *   writer.addDocument(document);
+ *   ...
+ *   // issue range query of 1960-1980
+ *   Query query = IntPoint.newRangeQuery("year", 1960, 1980);
+ *   TopDocs docs = searcher.search(query, ...);
+ * </pre>
+ * <h1>Geospatial Point Types</h1>
+ * Although basic point types such as {@link DoublePoint} support points in multi-dimensional space too, Lucene has
+ * specialized classes for location data. These classes are optimized for location data: they are more space-efficient and 
+ * support special operations such as <i>distance</i> and <i>polygon</i> queries. There are currently two implementations:
+ * <br>
+ * <ol>
+ *   <li><a href="{@docRoot}/../sandbox/org/apache/lucene/document/LatLonPoint.html">LatLonPoint</a> in <i>lucene-sandbox</i>: indexes {@code (latitude,longitude)} as {@code (x,y)} in two-dimensional space.
+ *   <li><a href="{@docRoot}/../spatial3d/org/apache/lucene/spatial3d/Geo3DPoint.html">Geo3DPoint</a>* in <i>lucene-spatial3d</i>: indexes {@code (latitude,longitude)} as {@code (x,y,z)} in three-dimensional space.
+ * </ol>
+ * * does <b>not</b> support altitude, 3D here means "uses three dimensions under-the-hood"<br>
+ * <h1>Advanced usage</h1>
+ * Custom structures can be created on top of single- or multi- dimensional basic types, on top of 
+ * {@link BinaryPoint} for more flexibility, or via custom {@link Field} subclasses.
  *
  *  @lucene.experimental */
 public abstract class PointValues {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5bb072d4/lucene/core/src/java/org/apache/lucene/search/PointInSetQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/PointInSetQuery.java b/lucene/core/src/java/org/apache/lucene/search/PointInSetQuery.java
index f5ba12d..944fadf 100644
--- a/lucene/core/src/java/org/apache/lucene/search/PointInSetQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/PointInSetQuery.java
@@ -16,15 +16,10 @@
  */
 package org.apache.lucene.search;
 
-
 import java.io.IOException;
 import java.util.Arrays;
 
-import org.apache.lucene.document.BinaryPoint;
-import org.apache.lucene.document.DoublePoint;
-import org.apache.lucene.document.FloatPoint;
 import org.apache.lucene.document.IntPoint;
-import org.apache.lucene.document.LongPoint;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
@@ -48,13 +43,7 @@ import org.apache.lucene.util.StringHelper;
  * create range queries for lucene's standard {@code Point} types, refer to factory
  * methods on those classes, e.g. {@link IntPoint#newSetQuery IntPoint.newSetQuery()} for 
  * fields indexed with {@link IntPoint}.
-
- * @see IntPoint
- * @see LongPoint
- * @see FloatPoint
- * @see DoublePoint
- * @see BinaryPoint 
- *
+ * @see PointValues
  * @lucene.experimental */
 
 public abstract class PointInSetQuery extends Query {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5bb072d4/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java b/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java
index 777c133..ebbe7e2 100644
--- a/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/PointRangeQuery.java
@@ -23,11 +23,7 @@ import java.util.Objects;
 import org.apache.lucene.index.PointValues;
 import org.apache.lucene.index.PointValues.IntersectVisitor;
 import org.apache.lucene.index.PointValues.Relation;
-import org.apache.lucene.document.BinaryPoint; // javadocs
-import org.apache.lucene.document.DoublePoint; // javadocs
-import org.apache.lucene.document.FloatPoint;  // javadocs
 import org.apache.lucene.document.IntPoint;    // javadocs
-import org.apache.lucene.document.LongPoint;   // javadocs
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
@@ -44,12 +40,7 @@ import org.apache.lucene.util.StringHelper;
  * fields indexed with {@link IntPoint}.
  * <p>
  * For a single-dimensional field this query is a simple range query; in a multi-dimensional field it's a box shape.
- * @see IntPoint
- * @see LongPoint
- * @see FloatPoint
- * @see DoublePoint
- * @see BinaryPoint 
- *
+ * @see PointValues
  * @lucene.experimental
  */
 public abstract class PointRangeQuery extends Query {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5bb072d4/lucene/sandbox/src/java/org/apache/lucene/document/BigIntegerPoint.java
----------------------------------------------------------------------
diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/BigIntegerPoint.java b/lucene/sandbox/src/java/org/apache/lucene/document/BigIntegerPoint.java
index f175858..70445d6 100644
--- a/lucene/sandbox/src/java/org/apache/lucene/document/BigIntegerPoint.java
+++ b/lucene/sandbox/src/java/org/apache/lucene/document/BigIntegerPoint.java
@@ -19,6 +19,7 @@ package org.apache.lucene.document;
 import java.math.BigInteger;
 import java.util.Arrays;
 
+import org.apache.lucene.index.PointValues;
 import org.apache.lucene.search.PointInSetQuery;
 import org.apache.lucene.search.PointRangeQuery;
 import org.apache.lucene.search.Query;
@@ -39,6 +40,7 @@ import org.apache.lucene.util.NumericUtils;
  *   <li>{@link #newRangeQuery(String, BigInteger, BigInteger)} for matching a 1D range.
  *   <li>{@link #newRangeQuery(String, BigInteger[], BigInteger[])} for matching points/ranges in n-dimensional space.
  * </ul>
+ * @see PointValues
  */
 public class BigIntegerPoint extends Field {
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5bb072d4/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java
----------------------------------------------------------------------
diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java b/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java
index a0623b3..f0df6ff 100644
--- a/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java
+++ b/lucene/sandbox/src/java/org/apache/lucene/document/InetAddressPoint.java
@@ -20,6 +20,7 @@ import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Arrays;
 
+import org.apache.lucene.index.PointValues;
 import org.apache.lucene.search.PointInSetQuery;
 import org.apache.lucene.search.PointRangeQuery;
 import org.apache.lucene.search.Query;
@@ -43,6 +44,7 @@ import org.apache.lucene.util.BytesRef;
  * This field supports both IPv4 and IPv6 addresses: IPv4 addresses are converted
  * to <a href="https://tools.ietf.org/html/rfc4291#section-2.5.5">IPv4-Mapped IPv6 Addresses</a>:
  * indexing {@code 1.2.3.4} is the same as indexing {@code ::FFFF:1.2.3.4}.
+ * @see PointValues
  */
 public class InetAddressPoint extends Field {
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5bb072d4/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java
----------------------------------------------------------------------
diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java
index 5f45cb5..fd3284b 100644
--- a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java
+++ b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java
@@ -20,6 +20,7 @@ import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.NumericUtils;
 
 import org.apache.lucene.index.FieldInfo;
+import org.apache.lucene.index.PointValues;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.ConstantScoreQuery;
@@ -43,6 +44,7 @@ import org.apache.lucene.spatial.util.GeoUtils;
  * <p>
  * <b>WARNING</b>: Values are indexed with some loss of precision, incurring up to 1E-7 error from the
  * original {@code double} values. 
+ * @see PointValues
  */
 // TODO ^^^ that is very sandy and hurts the API, usage, and tests tremendously, because what the user passes
 // to the field is not actually what gets indexed. Float would be 1E-5 error vs 1E-7, but it might be

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5bb072d4/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPoint.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPoint.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPoint.java
index cd2c79a..955a2bc 100644
--- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPoint.java
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPoint.java
@@ -18,6 +18,7 @@ package org.apache.lucene.spatial3d;
 
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.FieldType;
+import org.apache.lucene.index.PointValues;
 import org.apache.lucene.spatial3d.geom.GeoPoint;
 import org.apache.lucene.spatial3d.geom.GeoShape;
 import org.apache.lucene.spatial3d.geom.PlanetModel;
@@ -34,7 +35,7 @@ import org.apache.lucene.util.NumericUtils;
  * <ul>
  *   <li>{@link #newShapeQuery newShapeQuery()} for matching all points inside a specified shape
  * </ul>
- *
+ * @see PointValues
  *  @lucene.experimental */
 public final class Geo3DPoint extends Field {
 


[49/50] [abbrv] lucene-solr git commit: Merge remote-tracking branch 'remotes/origin/master' into apiv2

Posted by no...@apache.org.
Merge remote-tracking branch 'remotes/origin/master' into apiv2


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

Branch: refs/heads/apiv2
Commit: 781540855e41db12704cd54fa627486cf4be185a
Parents: 943f270 588aeea
Author: Noble Paul <no...@apache.org>
Authored: Wed Mar 9 21:26:15 2016 +0530
Committer: Noble Paul <no...@apache.org>
Committed: Wed Mar 9 21:26:15 2016 +0530

----------------------------------------------------------------------
 dev-tools/idea/.idea/ant.xml                    |     1 +
 dev-tools/idea/.idea/modules.xml                |     1 +
 dev-tools/idea/.idea/workspace.xml              |    41 +-
 .../idea/lucene/benchmark/src/benchmark.iml     |     2 +-
 .../lucene/spatial-extras/spatial-extras.iml    |    32 +
 dev-tools/idea/lucene/spatial/spatial.iml       |    15 -
 dev-tools/idea/solr/core/src/java/solr-core.iml |     2 +-
 .../idea/solr/core/src/solr-core-tests.iml      |     2 +-
 dev-tools/maven/lucene/pom.xml.template         |     1 +
 .../lucene/spatial-extras/pom.xml.template      |    62 +
 dev-tools/maven/lucene/spatial/pom.xml.template |     2 +-
 dev-tools/scripts/buildAndPushRelease.py        |     2 +-
 dev-tools/scripts/smokeTestRelease.py           |     7 +-
 lucene/CHANGES.txt                              |    60 +-
 lucene/MIGRATE.txt                              |    14 +-
 .../lucene/analysis/ar/ArabicAnalyzer.java      |     4 +-
 .../lucene/analysis/ckb/SoraniAnalyzer.java     |     4 +-
 .../lucene/analysis/fa/PersianAnalyzer.java     |     4 +-
 .../lucene/analysis/hi/HindiAnalyzer.java       |     4 +-
 .../miscellaneous/StemmerOverrideFilter.java    |     2 +-
 .../apache/lucene/analysis/th/ThaiAnalyzer.java |     5 +-
 .../lucene/analysis/ar/TestArabicAnalyzer.java  |    12 -
 .../lucene/analysis/ckb/TestSoraniAnalyzer.java |    12 -
 .../analysis/custom/TestCustomAnalyzer.java     |     8 +-
 .../lucene/analysis/fa/TestPersianAnalyzer.java |    12 -
 .../lucene/analysis/hi/TestHindiAnalyzer.java   |    12 -
 .../lucene/analysis/th/TestThaiAnalyzer.java    |    12 -
 .../lucene/codecs/lucene50/Lucene50Codec.java   |     6 +-
 .../lucene/codecs/lucene53/Lucene53Codec.java   |     8 +-
 .../lucene/codecs/lucene54/Lucene54Codec.java   |     8 +-
 .../index/TestBackwardsCompatibility.java       |    79 +-
 .../lucene/index/TestMaxPositionInOldIndex.java |   107 -
 .../org/apache/lucene/index/dvupdates.5.0.0.zip |   Bin 13376 -> 0 bytes
 .../org/apache/lucene/index/dvupdates.6.0.0.zip |   Bin 0 -> 3420 bytes
 .../org/apache/lucene/index/empty.5.0.0.zip     |   Bin 225 -> 0 bytes
 .../org/apache/lucene/index/empty.6.0.0.zip     |   Bin 0 -> 225 bytes
 .../org/apache/lucene/index/index.5.0.0-cfs.zip |   Bin 13503 -> 0 bytes
 .../apache/lucene/index/index.5.0.0-nocfs.zip   |   Bin 13485 -> 0 bytes
 .../index/index.5.0.0.singlesegment-cfs.zip     |   Bin 4028 -> 0 bytes
 .../index/index.5.0.0.singlesegment-nocfs.zip   |   Bin 6418 -> 0 bytes
 .../org/apache/lucene/index/index.5.1.0-cfs.zip |   Bin 13523 -> 0 bytes
 .../apache/lucene/index/index.5.1.0-nocfs.zip   |   Bin 13530 -> 0 bytes
 .../org/apache/lucene/index/index.5.2.0-cfs.zip |   Bin 13528 -> 0 bytes
 .../apache/lucene/index/index.5.2.0-nocfs.zip   |   Bin 13539 -> 0 bytes
 .../org/apache/lucene/index/index.5.2.1-cfs.zip |   Bin 13568 -> 0 bytes
 .../apache/lucene/index/index.5.2.1-nocfs.zip   |   Bin 13566 -> 0 bytes
 .../org/apache/lucene/index/index.5.3.0-cfs.zip |   Bin 13747 -> 0 bytes
 .../apache/lucene/index/index.5.3.0-nocfs.zip   |   Bin 13731 -> 0 bytes
 .../org/apache/lucene/index/index.5.3.1-cfs.zip |   Bin 13701 -> 0 bytes
 .../apache/lucene/index/index.5.3.1-nocfs.zip   |   Bin 13703 -> 0 bytes
 .../org/apache/lucene/index/index.5.3.2-cfs.zip |   Bin 13724 -> 0 bytes
 .../apache/lucene/index/index.5.3.2-nocfs.zip   |   Bin 13708 -> 0 bytes
 .../org/apache/lucene/index/index.5.4.0-cfs.zip |   Bin 13738 -> 0 bytes
 .../apache/lucene/index/index.5.4.0-nocfs.zip   |   Bin 13730 -> 0 bytes
 .../org/apache/lucene/index/index.5.4.1-cfs.zip |   Bin 13761 -> 0 bytes
 .../apache/lucene/index/index.5.4.1-nocfs.zip   |   Bin 13766 -> 0 bytes
 .../org/apache/lucene/index/index.5.5.0-cfs.zip |   Bin 24776 -> 0 bytes
 .../apache/lucene/index/index.5.5.0-nocfs.zip   |   Bin 13756 -> 0 bytes
 .../org/apache/lucene/index/moreterms.4.0.0.zip |   Bin 78661 -> 0 bytes
 .../org/apache/lucene/index/moreterms.5.0.0.zip |   Bin 78653 -> 0 bytes
 .../org/apache/lucene/index/moreterms.6.0.0.zip |   Bin 0 -> 157215 bytes
 .../lucene/index/unsupported.5.0.0-cfs.zip      |   Bin 0 -> 13503 bytes
 .../lucene/index/unsupported.5.0.0-nocfs.zip    |   Bin 0 -> 13485 bytes
 .../unsupported.5.0.0.singlesegment-cfs.zip     |   Bin 0 -> 4028 bytes
 .../unsupported.5.0.0.singlesegment-nocfs.zip   |   Bin 0 -> 6418 bytes
 .../lucene/index/unsupported.5.1.0-cfs.zip      |   Bin 0 -> 13523 bytes
 .../lucene/index/unsupported.5.1.0-nocfs.zip    |   Bin 0 -> 13530 bytes
 .../lucene/index/unsupported.5.2.0-cfs.zip      |   Bin 0 -> 13528 bytes
 .../lucene/index/unsupported.5.2.0-nocfs.zip    |   Bin 0 -> 13539 bytes
 .../lucene/index/unsupported.5.2.1-cfs.zip      |   Bin 0 -> 13568 bytes
 .../lucene/index/unsupported.5.2.1-nocfs.zip    |   Bin 0 -> 13566 bytes
 .../lucene/index/unsupported.5.3.0-cfs.zip      |   Bin 0 -> 13747 bytes
 .../lucene/index/unsupported.5.3.0-nocfs.zip    |   Bin 0 -> 13731 bytes
 .../lucene/index/unsupported.5.3.1-cfs.zip      |   Bin 0 -> 13701 bytes
 .../lucene/index/unsupported.5.3.1-nocfs.zip    |   Bin 0 -> 13703 bytes
 .../lucene/index/unsupported.5.3.2-cfs.zip      |   Bin 0 -> 13724 bytes
 .../lucene/index/unsupported.5.3.2-nocfs.zip    |   Bin 0 -> 13708 bytes
 .../lucene/index/unsupported.5.4.0-cfs.zip      |   Bin 0 -> 13738 bytes
 .../lucene/index/unsupported.5.4.0-nocfs.zip    |   Bin 0 -> 13730 bytes
 .../lucene/index/unsupported.5.4.1-cfs.zip      |   Bin 0 -> 13761 bytes
 .../lucene/index/unsupported.5.4.1-nocfs.zip    |   Bin 0 -> 13766 bytes
 .../lucene/index/unsupported.5.5.0-cfs.zip      |   Bin 0 -> 24776 bytes
 .../lucene/index/unsupported.5.5.0-nocfs.zip    |   Bin 0 -> 13756 bytes
 lucene/benchmark/build.xml                      |     8 +-
 lucene/benchmark/conf/spatial.alg               |     2 +-
 lucene/benchmark/ivy.xml                        |     2 +-
 .../lucene/benchmark/byTask/feeds/DocMaker.java |    44 +-
 .../benchmark/byTask/feeds/SpatialDocMaker.java |     8 +-
 .../byTask/feeds/SpatialFileQueryMaker.java     |     4 +-
 .../benchmark/byTask/tasks/ReadTokensTask.java  |    13 +-
 lucene/build.xml                                |     5 +-
 .../codecs/blockterms/BlockTermsReader.java     |     4 +-
 .../lucene/codecs/memory/FSTTermsWriter.java    |     2 +-
 .../codecs/simpletext/SimpleTextBKDReader.java  |    10 +-
 .../codecs/simpletext/SimpleTextCodec.java      |     8 +-
 .../simpletext/SimpleTextPointFormat.java       |    53 -
 .../simpletext/SimpleTextPointReader.java       |   270 -
 .../simpletext/SimpleTextPointWriter.java       |   230 -
 .../simpletext/SimpleTextPointsFormat.java      |    53 +
 .../simpletext/SimpleTextPointsReader.java      |   302 +
 .../simpletext/SimpleTextPointsWriter.java      |   244 +
 .../simpletext/TestSimpleTextPointFormat.java   |    33 -
 .../simpletext/TestSimpleTextPointsFormat.java  |    33 +
 .../analysis/LegacyNumericTokenStream.java      |     5 +-
 .../java/org/apache/lucene/codecs/Codec.java    |     2 +-
 .../org/apache/lucene/codecs/FilterCodec.java   |     4 +-
 .../org/apache/lucene/codecs/PointFormat.java   |   101 -
 .../org/apache/lucene/codecs/PointReader.java   |    51 -
 .../org/apache/lucene/codecs/PointWriter.java   |   134 -
 .../org/apache/lucene/codecs/PointsFormat.java  |   111 +
 .../org/apache/lucene/codecs/PointsReader.java  |    51 +
 .../org/apache/lucene/codecs/PointsWriter.java  |   157 +
 .../lucene/codecs/lucene60/Lucene60Codec.java   |     6 +-
 .../codecs/lucene60/Lucene60PointFormat.java    |   106 -
 .../codecs/lucene60/Lucene60PointReader.java    |   219 -
 .../codecs/lucene60/Lucene60PointWriter.java    |   218 -
 .../codecs/lucene60/Lucene60PointsFormat.java   |   106 +
 .../codecs/lucene60/Lucene60PointsReader.java   |   241 +
 .../codecs/lucene60/Lucene60PointsWriter.java   |   225 +
 .../lucene/codecs/lucene60/package-info.java    |    11 +-
 .../org/apache/lucene/document/BinaryPoint.java |   151 +-
 .../org/apache/lucene/document/Document.java    |     6 +-
 .../document/DocumentStoredFieldVisitor.java    |     7 +-
 .../org/apache/lucene/document/DoublePoint.java |   168 +-
 .../java/org/apache/lucene/document/Field.java  |    19 +-
 .../org/apache/lucene/document/FieldType.java   |    36 +-
 .../org/apache/lucene/document/FloatPoint.java  |   168 +-
 .../org/apache/lucene/document/IntPoint.java    |   166 +-
 .../org/apache/lucene/document/LongPoint.java   |   170 +-
 .../document/SortedNumericDocValuesField.java   |     4 +-
 .../org/apache/lucene/document/StoredField.java |     4 +-
 .../org/apache/lucene/index/CheckIndex.java     |   137 +-
 .../org/apache/lucene/index/CodecReader.java    |    19 +-
 .../lucene/index/DefaultIndexingChain.java      |    22 +-
 .../java/org/apache/lucene/index/FieldInfo.java |     2 +-
 .../apache/lucene/index/FilterCodecReader.java  |     8 +-
 .../apache/lucene/index/FilterLeafReader.java   |    10 +-
 .../index/IndexFormatTooOldException.java       |     4 +-
 .../org/apache/lucene/index/IndexUpgrader.java  |     2 +-
 .../org/apache/lucene/index/IndexWriter.java    |     1 +
 .../org/apache/lucene/index/LeafReader.java     |     2 +-
 .../org/apache/lucene/index/MergeState.java     |    12 +-
 .../apache/lucene/index/MultiPointValues.java   |   172 -
 .../apache/lucene/index/ParallelLeafReader.java |    26 +
 .../org/apache/lucene/index/PointValues.java    |    68 +-
 .../apache/lucene/index/PointValuesWriter.java  |    19 +-
 .../apache/lucene/index/PrefixCodedTerms.java   |     2 +-
 .../apache/lucene/index/SegmentCoreReaders.java |    10 +-
 .../org/apache/lucene/index/SegmentInfos.java   |    28 +-
 .../org/apache/lucene/index/SegmentMerger.java  |     4 +-
 .../org/apache/lucene/index/SegmentReader.java  |     8 +-
 .../lucene/index/SlowCodecReaderWrapper.java    |    18 +-
 .../index/SlowCompositeReaderWrapper.java       |     2 +-
 .../lucene/index/SortedDocValuesWriter.java     |     2 +-
 .../lucene/index/SortedSetDocValuesWriter.java  |     2 +-
 .../apache/lucene/index/TermsHashPerField.java  |     2 +-
 .../apache/lucene/search/FieldValueQuery.java   |     4 +
 .../apache/lucene/search/FilterCollector.java   |     2 +-
 .../lucene/search/FilterLeafCollector.java      |     2 +-
 .../apache/lucene/search/FuzzyTermsEnum.java    |     5 +-
 .../lucene/search/LegacyNumericRangeQuery.java  |    29 +-
 .../apache/lucene/search/MultiPhraseQuery.java  |   273 +-
 .../MultiTermQueryConstantScoreWrapper.java     |     3 +
 .../apache/lucene/search/NGramPhraseQuery.java  |     5 +
 .../apache/lucene/search/PointInSetQuery.java   |   363 +
 .../apache/lucene/search/PointRangeQuery.java   |   696 +-
 .../org/apache/lucene/search/RegexpQuery.java   |     7 +-
 .../apache/lucene/search/ScoringRewrite.java    |     2 +-
 .../org/apache/lucene/search/SortField.java     |     2 +-
 .../lucene/search/SortedNumericSelector.java    |     6 +-
 .../org/apache/lucene/search/SynonymQuery.java  |     5 +
 .../search/UsageTrackingQueryCachingPolicy.java |    16 +-
 .../lucene/search/spans/SpanContainQuery.java   |     8 +
 .../apache/lucene/store/FilterDirectory.java    |     2 +-
 .../org/apache/lucene/store/MMapDirectory.java  |    10 +-
 .../java/org/apache/lucene/util/ArrayUtil.java  |    20 +-
 .../org/apache/lucene/util/ByteBlockPool.java   |    22 +
 .../java/org/apache/lucene/util/BytesRef.java   |   122 +-
 .../org/apache/lucene/util/BytesRefArray.java   |    41 +-
 .../org/apache/lucene/util/BytesRefHash.java    |    10 +-
 .../org/apache/lucene/util/CollectionUtil.java  |     4 +-
 .../org/apache/lucene/util/DocIdSetBuilder.java |    14 +-
 .../apache/lucene/util/LegacyNumericUtils.java  |    63 -
 .../org/apache/lucene/util/NumericUtils.java    |   200 +-
 .../org/apache/lucene/util/OfflineSorter.java   |     7 +-
 .../org/apache/lucene/util/QueryBuilder.java    |    18 +-
 .../apache/lucene/util/RamUsageEstimator.java   |    49 +
 .../org/apache/lucene/util/StringHelper.java    |     1 +
 .../java/org/apache/lucene/util/Version.java    |    78 +-
 .../org/apache/lucene/util/bkd/BKDReader.java   |    26 +-
 .../org/apache/lucene/util/bkd/BKDWriter.java   |    94 +-
 .../lucene60/TestLucene60PointFormat.java       |    83 -
 .../lucene60/TestLucene60PointsFormat.java      |    83 +
 .../apache/lucene/document/TestDocument.java    |     4 +-
 .../org/apache/lucene/document/TestField.java   |   184 +-
 .../apache/lucene/document/TestFieldType.java   |    21 +-
 .../index/TestDemoParallelLeafReader.java       |     3 +-
 .../apache/lucene/index/TestDuelingCodecs.java  |     4 +-
 .../lucene/index/TestFilterLeafReader.java      |     2 +-
 .../index/TestFlushByRamOrCountsPolicy.java     |     2 +-
 .../lucene/index/TestForceMergeForever.java     |     2 +-
 .../apache/lucene/index/TestMultiFields.java    |     4 +-
 .../test/org/apache/lucene/index/TestNorms.java |     2 +-
 .../apache/lucene/index/TestPointValues.java    |   154 +-
 .../apache/lucene/index/TestRollingUpdates.java |     2 +-
 .../apache/lucene/index/TestSegmentInfos.java   |    10 +-
 .../test/org/apache/lucene/index/TestTerms.java |    10 +-
 .../org/apache/lucene/index/TestTermsEnum.java  |     2 +-
 .../lucene/search/TestComplexExplanations.java  |    10 +-
 .../lucene/search/TestMultiPhraseQuery.java     |   190 +-
 .../lucene/search/TestNumericRangeQuery32.java  |     3 +-
 .../lucene/search/TestNumericRangeQuery64.java  |     3 +-
 .../lucene/search/TestPhrasePrefixQuery.java    |    16 +-
 .../apache/lucene/search/TestPointQueries.java  |  1196 +-
 .../lucene/search/TestPositionIncrement.java    |     6 +-
 .../lucene/search/TestSimpleExplanations.java   |    52 +-
 .../search/TestSimpleSearchEquivalence.java     |    16 +-
 .../lucene/search/TestSloppyPhraseQuery2.java   |    10 +-
 .../search/TestSortedNumericSortField.java      |    15 +-
 .../TestUsageTrackingFilterCachingPolicy.java   |     4 +-
 .../lucene/store/TestFilterDirectory.java       |     4 +-
 .../lucene/store/TestNRTCachingDirectory.java   |     2 +-
 .../apache/lucene/util/TestBytesRefArray.java   |     5 +-
 .../apache/lucene/util/TestBytesRefHash.java    |    12 +-
 .../lucene/util/TestInPlaceMergeSorter.java     |     4 +-
 .../org/apache/lucene/util/TestIntroSorter.java |     4 +-
 .../lucene/util/TestLegacyNumericUtils.java     |    16 +-
 .../apache/lucene/util/TestNumericUtils.java    |   491 +
 .../apache/lucene/util/TestQueryBuilder.java    |    20 +-
 .../org/apache/lucene/util/TestTimSorter.java   |     3 +-
 .../org/apache/lucene/util/TestUnicodeUtil.java |    15 +-
 .../org/apache/lucene/util/TestVersion.java     |    18 +-
 .../org/apache/lucene/util/bkd/TestBKD.java     |   139 +-
 .../org/apache/lucene/util/fst/TestFSTs.java    |     2 +-
 .../demo/facet/DistanceFacetsExample.java       |    10 +-
 .../lucene/demo/facet/RangeFacetsExample.java   |     5 +-
 .../apache/lucene/facet/range/DoubleRange.java  |    37 +-
 .../facet/range/DoubleRangeFacetCounts.java     |     8 +-
 .../apache/lucene/facet/range/LongRange.java    |    25 +-
 .../lucene/facet/range/LongRangeCounter.java    |    14 +-
 .../facet/range/TestRangeFacetCounts.java       |   215 +-
 .../highlight/WeightedSpanTermExtractor.java    |     6 +-
 .../search/highlight/HighlighterTest.java       |    19 +-
 lucene/ivy-versions.properties                  |     3 +-
 .../lucene/search/join/GlobalOrdinalsQuery.java |    27 +-
 .../join/GlobalOrdinalsWithScoreQuery.java      |    35 +-
 .../search/join/TermsIncludingScoreQuery.java   |     2 +-
 .../apache/lucene/search/join/TermsQuery.java   |    11 +-
 .../search/join/ToParentBlockJoinSortField.java |     6 +-
 .../lucene/search/join/TestBlockJoin.java       |    72 +-
 .../apache/lucene/search/join/TestJoinUtil.java |   105 +-
 lucene/licenses/spatial4j-0.5-tests.jar.sha1    |     1 -
 lucene/licenses/spatial4j-0.5.jar.sha1          |     1 -
 lucene/licenses/spatial4j-0.6-tests.jar.sha1    |     1 +
 lucene/licenses/spatial4j-0.6.jar.sha1          |     1 +
 lucene/licenses/spatial4j-NOTICE.txt            |   136 +-
 .../apache/lucene/index/memory/MemoryIndex.java |    13 +-
 .../apache/lucene/index/SortingLeafReader.java  |    10 +
 .../org/apache/lucene/index/SorterTestBase.java |     8 +-
 lucene/module-build.xml                         |    22 +
 .../apache/lucene/queries/BoostingQuery.java    |    12 +
 .../apache/lucene/queries/CommonTermsQuery.java |    44 +
 .../org/apache/lucene/queries/TermsQuery.java   |     5 +
 .../queries/function/FunctionRangeQuery.java    |    20 +
 .../apache/lucene/queries/TermsQueryTest.java   |    25 +
 .../queries/function/FunctionTestSetup.java     |     8 +-
 .../queries/function/TestFunctionQuerySort.java |     4 +-
 .../queries/function/TestValueSources.java      |    16 -
 .../classic/MultiFieldQueryParser.java          |     6 +-
 .../queryparser/classic/QueryParserBase.java    |     9 +-
 .../builders/MultiPhraseQueryNodeBuilder.java   |     6 +-
 .../standard/builders/SlopQueryNodeBuilder.java |     8 +-
 .../classic/TestMultiPhraseQueryParsing.java    |    10 +-
 .../queryparser/classic/TestQueryParser.java    |    28 +-
 .../apache/lucene/document/BigIntegerPoint.java |   260 +
 .../lucene/document/InetAddressPoint.java       |   247 +
 .../org/apache/lucene/document/LatLonPoint.java |   293 +-
 .../document/LatLonPointDistanceQuery.java      |   209 +
 .../document/LatLonPointInPolygonQuery.java     |   254 +
 .../org/apache/lucene/document/package.html     |     7 +-
 .../apache/lucene/payloads/PayloadSpanUtil.java |     6 +-
 .../lucene/search/DocValuesNumbersQuery.java    |     8 +
 .../lucene/search/DocValuesRangeQuery.java      |    20 +
 .../lucene/search/DocValuesTermsQuery.java      |     2 +-
 .../lucene/search/PointInPolygonQuery.java      |   211 -
 .../apache/lucene/search/PointInRectQuery.java  |   200 -
 .../lucene/document/TestBigIntegerPoint.java    |    96 +
 .../lucene/document/TestInetAddressPoint.java   |    91 +
 .../apache/lucene/document/TestLatLonPoint.java |   173 +
 .../document/TestLatLonPointDistanceQuery.java  |   190 +
 .../lucene/search/TestDocValuesRangeQuery.java  |    33 +-
 .../lucene/search/TestLatLonPointQueries.java   |   175 +-
 .../lucene/search/TestTermAutomatonQuery.java   |     8 +-
 lucene/spatial-extras/build.xml                 |    57 +
 lucene/spatial-extras/ivy.xml                   |    36 +
 .../apache/lucene/spatial/SpatialStrategy.java  |   149 +
 .../bbox/BBoxOverlapRatioValueSource.java       |   251 +
 .../spatial/bbox/BBoxSimilarityValueSource.java |   117 +
 .../lucene/spatial/bbox/BBoxStrategy.java       |   589 +
 .../lucene/spatial/bbox/BBoxValueSource.java    |   115 +
 .../lucene/spatial/bbox/package-info.java       |    23 +
 .../composite/CompositeSpatialStrategy.java     |   144 +
 .../spatial/composite/CompositeVerifyQuery.java |   120 +
 .../composite/IntersectsRPTVerifyQuery.java     |   235 +
 .../lucene/spatial/composite/package-info.java  |    19 +
 .../java/org/apache/lucene/spatial/package.html |    26 +
 .../spatial/prefix/AbstractPrefixTreeQuery.java |   133 +
 .../prefix/AbstractVisitingPrefixTreeQuery.java |   380 +
 .../prefix/BytesRefIteratorTokenStream.java     |    72 +
 .../spatial/prefix/CellToBytesRefIterator.java  |    49 +
 .../spatial/prefix/ContainsPrefixTreeQuery.java |   362 +
 .../spatial/prefix/HeatmapFacetCounter.java     |   310 +
 .../prefix/IntersectsPrefixTreeQuery.java       |    95 +
 .../prefix/NumberRangePrefixTreeStrategy.java   |   199 +
 .../PointPrefixTreeFieldCacheProvider.java      |    48 +
 .../spatial/prefix/PrefixTreeFacetCounter.java  |   201 +
 .../spatial/prefix/PrefixTreeStrategy.java      |   208 +
 .../prefix/RecursivePrefixTreeStrategy.java     |   192 +
 .../prefix/TermQueryPrefixTreeStrategy.java     |   111 +
 .../spatial/prefix/WithinPrefixTreeQuery.java   |   232 +
 .../lucene/spatial/prefix/package-info.java     |    21 +
 .../apache/lucene/spatial/prefix/tree/Cell.java |   109 +
 .../spatial/prefix/tree/CellIterator.java       |    76 +
 .../prefix/tree/DateRangePrefixTree.java        |   444 +
 .../spatial/prefix/tree/FilterCellIterator.java |    61 +
 .../spatial/prefix/tree/GeohashPrefixTree.java  |   162 +
 .../lucene/spatial/prefix/tree/LegacyCell.java  |   242 +
 .../spatial/prefix/tree/LegacyPrefixTree.java   |    84 +
 .../prefix/tree/NumberRangePrefixTree.java      |   989 +
 .../prefix/tree/PackedQuadPrefixTree.java       |   459 +
 .../spatial/prefix/tree/QuadPrefixTree.java     |   308 +
 .../prefix/tree/SingletonCellIterator.java      |    36 +
 .../spatial/prefix/tree/SpatialPrefixTree.java  |   117 +
 .../prefix/tree/SpatialPrefixTreeFactory.java   |    99 +
 .../spatial/prefix/tree/TreeCellIterator.java   |    87 +
 .../spatial/prefix/tree/package-info.java       |    30 +
 .../lucene/spatial/query/SpatialArgs.java       |   148 +
 .../lucene/spatial/query/SpatialArgsParser.java |   146 +
 .../lucene/spatial/query/SpatialOperation.java  |   179 +
 .../query/UnsupportedSpatialOperation.java      |    28 +
 .../lucene/spatial/query/package-info.java      |    21 +
 .../serialized/SerializedDVStrategy.java        |   278 +
 .../lucene/spatial/serialized/package-info.java |    21 +
 .../lucene/spatial/spatial4j/Geo3dShape.java    |   185 +
 .../lucene/spatial/spatial4j/package-info.java  |    19 +
 .../spatial/util/CachingDoubleValueSource.java  |    93 +
 .../util/DistanceToShapeValueSource.java        |   122 +
 .../spatial/util/ShapeAreaValueSource.java      |   116 +
 .../lucene/spatial/util/ShapeFieldCache.java    |    54 +
 .../ShapeFieldCacheDistanceValueSource.java     |   112 +
 .../spatial/util/ShapeFieldCacheProvider.java   |    87 +
 .../spatial/util/ShapePredicateValueSource.java |   113 +
 .../org/apache/lucene/spatial/util/package.html |    26 +
 .../spatial/vector/DistanceValueSource.java     |   120 +
 .../spatial/vector/PointVectorStrategy.java     |   178 +
 .../lucene/spatial/vector/package-info.java     |    21 +
 lucene/spatial-extras/src/java/overview.html    |    67 +
 .../src/test-files/cities-Intersects-BBox.txt   |     3 +
 .../src/test-files/data/LUCENE-4464.txt         |     3 +
 .../src/test-files/data/countries-bbox.txt      |   249 +
 .../src/test-files/data/countries-poly.txt      |   249 +
 .../src/test-files/data/geonames-IE.txt         | 22929 +++++++++++++++++
 .../src/test-files/data/simple-bbox.txt         |     4 +
 .../src/test-files/data/states-bbox.txt         |    52 +
 .../src/test-files/data/states-poly.txt         |    52 +
 .../src/test-files/data/world-cities-points.txt |  2680 ++
 .../src/test-files/simple-Queries-BBox.txt      |     9 +
 .../src/test-files/states-Intersects-BBox.txt   |     3 +
 .../src/test-files/states-IsWithin-BBox.txt     |     4 +
 .../lucene/spatial/DistanceStrategyTest.java    |   135 +
 .../apache/lucene/spatial/PortedSolr3Test.java  |   167 +
 .../lucene/spatial/QueryEqualsHashCodeTest.java |   119 +
 .../apache/lucene/spatial/SpatialArgsTest.java  |    50 +
 .../apache/lucene/spatial/SpatialExample.java   |   200 +
 .../lucene/spatial/SpatialMatchConcern.java     |    31 +
 .../apache/lucene/spatial/SpatialTestCase.java  |   280 +
 .../apache/lucene/spatial/SpatialTestData.java  |    71 +
 .../apache/lucene/spatial/SpatialTestQuery.java |    96 +
 .../apache/lucene/spatial/StrategyTestCase.java |   252 +
 .../lucene/spatial/TestTestFramework.java       |    68 +
 .../lucene/spatial/bbox/TestBBoxStrategy.java   |   301 +
 .../composite/CompositeStrategyTest.java        |   142 +
 .../prefix/CellToBytesRefIterator50.java        |    44 +
 .../spatial/prefix/DateNRStrategyTest.java      |   143 +
 .../spatial/prefix/HeatmapFacetCounterTest.java |   252 +
 .../lucene/spatial/prefix/JtsPolygonTest.java   |   117 +
 .../spatial/prefix/NumberRangeFacetsTest.java   |   275 +
 .../RandomSpatialOpFuzzyPrefixTree50Test.java   |    31 +
 .../RandomSpatialOpFuzzyPrefixTreeTest.java     |   533 +
 .../prefix/RandomSpatialOpStrategyTestCase.java |   141 +
 .../prefix/TestRecursivePrefixTreeStrategy.java |   122 +
 .../prefix/TestTermQueryPrefixGridStrategy.java |    63 +
 .../prefix/tree/DateRangePrefixTreeTest.java    |   175 +
 .../prefix/tree/SpatialPrefixTreeTest.java      |   114 +
 .../spatial/query/SpatialArgsParserTest.java    |    77 +
 .../serialized/SerializedStrategyTest.java      |    66 +
 .../lucene/spatial/spatial4j/Geo3dRptTest.java  |   227 +
 .../Geo3dShapeRectRelationTestCase.java         |   258 +
 .../Geo3dShapeSphereModelRectRelationTest.java  |    72 +
 .../Geo3dShapeWGS84ModelRectRelationTest.java   |    94 +
 .../spatial4j/RandomizedShapeTestCase.java      |   288 +
 .../spatial/vector/TestPointVectorStrategy.java |    63 +
 lucene/spatial/build.xml                        |    30 -
 lucene/spatial/ivy.xml                          |    15 -
 .../apache/lucene/spatial/SpatialStrategy.java  |   149 -
 .../bbox/BBoxOverlapRatioValueSource.java       |   251 -
 .../spatial/bbox/BBoxSimilarityValueSource.java |   117 -
 .../lucene/spatial/bbox/BBoxStrategy.java       |   591 -
 .../lucene/spatial/bbox/BBoxValueSource.java    |   115 -
 .../lucene/spatial/bbox/package-info.java       |    23 -
 .../composite/CompositeSpatialStrategy.java     |   144 -
 .../spatial/composite/CompositeVerifyQuery.java |   121 -
 .../composite/IntersectsRPTVerifyQuery.java     |   235 -
 .../lucene/spatial/composite/package-info.java  |    19 -
 .../geopoint/search/GeoPointDistanceQuery.java  |     5 +
 .../search/GeoPointDistanceRangeQuery.java      |     6 +
 .../geopoint/search/GeoPointInBBoxQuery.java    |    10 +
 .../geopoint/search/GeoPointInPolygonQuery.java |     6 +
 .../GeoPointTermQueryConstantScoreWrapper.java  |     7 +
 .../spatial/prefix/AbstractPrefixTreeQuery.java |   133 -
 .../prefix/AbstractVisitingPrefixTreeQuery.java |   380 -
 .../prefix/BytesRefIteratorTokenStream.java     |    72 -
 .../spatial/prefix/CellToBytesRefIterator.java  |    49 -
 .../spatial/prefix/ContainsPrefixTreeQuery.java |   362 -
 .../spatial/prefix/HeatmapFacetCounter.java     |   310 -
 .../prefix/IntersectsPrefixTreeQuery.java       |    95 -
 .../prefix/NumberRangePrefixTreeStrategy.java   |   199 -
 .../PointPrefixTreeFieldCacheProvider.java      |    48 -
 .../spatial/prefix/PrefixTreeFacetCounter.java  |   201 -
 .../spatial/prefix/PrefixTreeStrategy.java      |   208 -
 .../prefix/RecursivePrefixTreeStrategy.java     |   196 -
 .../prefix/TermQueryPrefixTreeStrategy.java     |   111 -
 .../spatial/prefix/WithinPrefixTreeQuery.java   |   233 -
 .../lucene/spatial/prefix/package-info.java     |    21 -
 .../apache/lucene/spatial/prefix/tree/Cell.java |   109 -
 .../spatial/prefix/tree/CellIterator.java       |    76 -
 .../prefix/tree/DateRangePrefixTree.java        |   444 -
 .../spatial/prefix/tree/FilterCellIterator.java |    61 -
 .../spatial/prefix/tree/GeohashPrefixTree.java  |   162 -
 .../lucene/spatial/prefix/tree/LegacyCell.java  |   242 -
 .../spatial/prefix/tree/LegacyPrefixTree.java   |    84 -
 .../prefix/tree/NumberRangePrefixTree.java      |   989 -
 .../prefix/tree/PackedQuadPrefixTree.java       |   459 -
 .../spatial/prefix/tree/QuadPrefixTree.java     |   308 -
 .../prefix/tree/SingletonCellIterator.java      |    36 -
 .../spatial/prefix/tree/SpatialPrefixTree.java  |   117 -
 .../prefix/tree/SpatialPrefixTreeFactory.java   |    99 -
 .../spatial/prefix/tree/TreeCellIterator.java   |    87 -
 .../spatial/prefix/tree/package-info.java       |    30 -
 .../lucene/spatial/query/SpatialArgs.java       |   148 -
 .../lucene/spatial/query/SpatialArgsParser.java |   146 -
 .../lucene/spatial/query/SpatialOperation.java  |   179 -
 .../query/UnsupportedSpatialOperation.java      |    28 -
 .../lucene/spatial/query/package-info.java      |    21 -
 .../serialized/SerializedDVStrategy.java        |   278 -
 .../lucene/spatial/serialized/package-info.java |    21 -
 .../lucene/spatial/spatial4j/Geo3dShape.java    |   185 -
 .../lucene/spatial/spatial4j/package-info.java  |    19 -
 .../spatial/util/CachingDoubleValueSource.java  |    93 -
 .../util/DistanceToShapeValueSource.java        |   122 -
 .../lucene/spatial/util/GeoEncodingUtils.java   |    26 +-
 .../org/apache/lucene/spatial/util/GeoRect.java |    12 +
 .../lucene/spatial/util/GeoRelationUtils.java   |     4 +
 .../spatial/util/ShapeAreaValueSource.java      |   116 -
 .../lucene/spatial/util/ShapeFieldCache.java    |    54 -
 .../ShapeFieldCacheDistanceValueSource.java     |   112 -
 .../spatial/util/ShapeFieldCacheProvider.java   |    87 -
 .../spatial/util/ShapePredicateValueSource.java |   113 -
 .../spatial/vector/DistanceValueSource.java     |   120 -
 .../spatial/vector/PointVectorStrategy.java     |   182 -
 .../lucene/spatial/vector/package-info.java     |    21 -
 lucene/spatial/src/java/overview.html           |    50 +-
 .../src/test-files/cities-Intersects-BBox.txt   |     3 -
 .../spatial/src/test-files/data/LUCENE-4464.txt |     3 -
 .../src/test-files/data/countries-bbox.txt      |   249 -
 .../src/test-files/data/countries-poly.txt      |   249 -
 .../spatial/src/test-files/data/geonames-IE.txt | 22929 -----------------
 .../spatial/src/test-files/data/simple-bbox.txt |     5 -
 .../spatial/src/test-files/data/states-bbox.txt |    52 -
 .../spatial/src/test-files/data/states-poly.txt |    52 -
 .../src/test-files/data/world-cities-points.txt |  2680 --
 .../src/test-files/simple-Queries-BBox.txt      |     9 -
 .../src/test-files/states-Intersects-BBox.txt   |     3 -
 .../src/test-files/states-IsWithin-BBox.txt     |     4 -
 .../lucene/spatial/DistanceStrategyTest.java    |   135 -
 .../apache/lucene/spatial/PortedSolr3Test.java  |   167 -
 .../lucene/spatial/QueryEqualsHashCodeTest.java |   119 -
 .../apache/lucene/spatial/SpatialArgsTest.java  |    50 -
 .../apache/lucene/spatial/SpatialExample.java   |   200 -
 .../lucene/spatial/SpatialMatchConcern.java     |    31 -
 .../apache/lucene/spatial/SpatialTestCase.java  |   281 -
 .../apache/lucene/spatial/SpatialTestData.java  |    71 -
 .../apache/lucene/spatial/SpatialTestQuery.java |    96 -
 .../apache/lucene/spatial/StrategyTestCase.java |   252 -
 .../lucene/spatial/TestTestFramework.java       |    68 -
 .../lucene/spatial/bbox/TestBBoxStrategy.java   |   301 -
 .../composite/CompositeStrategyTest.java        |   142 -
 .../prefix/CellToBytesRefIterator50.java        |    44 -
 .../spatial/prefix/DateNRStrategyTest.java      |   143 -
 .../spatial/prefix/HeatmapFacetCounterTest.java |   252 -
 .../lucene/spatial/prefix/JtsPolygonTest.java   |   117 -
 .../spatial/prefix/NumberRangeFacetsTest.java   |   275 -
 .../RandomSpatialOpFuzzyPrefixTree50Test.java   |    31 -
 .../RandomSpatialOpFuzzyPrefixTreeTest.java     |   533 -
 .../prefix/RandomSpatialOpStrategyTestCase.java |   141 -
 .../prefix/TestRecursivePrefixTreeStrategy.java |   122 -
 .../prefix/TestTermQueryPrefixGridStrategy.java |    63 -
 .../prefix/tree/DateRangePrefixTreeTest.java    |   175 -
 .../prefix/tree/SpatialPrefixTreeTest.java      |   114 -
 .../spatial/query/SpatialArgsParserTest.java    |    77 -
 .../serialized/SerializedStrategyTest.java      |    66 -
 .../lucene/spatial/spatial4j/Geo3dRptTest.java  |   227 -
 .../Geo3dShapeRectRelationTestCase.java         |   264 -
 .../Geo3dShapeSphereModelRectRelationTest.java  |    72 -
 .../Geo3dShapeWGS84ModelRectRelationTest.java   |    95 -
 .../spatial4j/RandomizedShapeTestCase.java      |   289 -
 .../spatial/spatial4j/geo3d/GeoPointTest.java   |    82 -
 .../spatial/util/BaseGeoPointTestCase.java      |    94 +-
 .../spatial/vector/TestPointVectorStrategy.java |    63 -
 .../org/apache/lucene/geo3d/ArcDistance.java    |    56 -
 .../apache/lucene/geo3d/BasePlanetObject.java   |    52 -
 .../org/apache/lucene/geo3d/BaseXYZSolid.java   |   167 -
 .../java/org/apache/lucene/geo3d/Bounds.java    |   113 -
 .../org/apache/lucene/geo3d/DistanceStyle.java  |    83 -
 .../org/apache/lucene/geo3d/Geo3DPoint.java     |    68 -
 .../java/org/apache/lucene/geo3d/Geo3DUtil.java |    59 -
 .../java/org/apache/lucene/geo3d/GeoArea.java   |    67 -
 .../org/apache/lucene/geo3d/GeoAreaFactory.java |    55 -
 .../java/org/apache/lucene/geo3d/GeoBBox.java   |    36 -
 .../org/apache/lucene/geo3d/GeoBBoxFactory.java |   111 -
 .../org/apache/lucene/geo3d/GeoBaseBBox.java    |    72 -
 .../org/apache/lucene/geo3d/GeoBaseCircle.java  |    34 -
 .../lucene/geo3d/GeoBaseDistanceShape.java      |    56 -
 .../lucene/geo3d/GeoBaseMembershipShape.java    |    56 -
 .../org/apache/lucene/geo3d/GeoBasePolygon.java |    34 -
 .../org/apache/lucene/geo3d/GeoBaseShape.java   |    59 -
 .../java/org/apache/lucene/geo3d/GeoCircle.java |    25 -
 .../apache/lucene/geo3d/GeoCircleFactory.java   |    43 -
 .../geo3d/GeoCompositeMembershipShape.java      |   117 -
 .../lucene/geo3d/GeoCompositePolygon.java       |    31 -
 .../apache/lucene/geo3d/GeoConvexPolygon.java   |   288 -
 .../geo3d/GeoDegenerateHorizontalLine.java      |   215 -
 .../lucene/geo3d/GeoDegenerateLatitudeZone.java |   138 -
 .../geo3d/GeoDegenerateLongitudeSlice.java      |   153 -
 .../apache/lucene/geo3d/GeoDegeneratePoint.java |   135 -
 .../lucene/geo3d/GeoDegenerateVerticalLine.java |   205 -
 .../org/apache/lucene/geo3d/GeoDistance.java    |    59 -
 .../apache/lucene/geo3d/GeoDistanceShape.java   |    27 -
 .../apache/lucene/geo3d/GeoLatitudeZone.java    |   198 -
 .../apache/lucene/geo3d/GeoLongitudeSlice.java  |   204 -
 .../apache/lucene/geo3d/GeoMembershipShape.java |    27 -
 .../lucene/geo3d/GeoNorthLatitudeZone.java      |   165 -
 .../apache/lucene/geo3d/GeoNorthRectangle.java  |   263 -
 .../apache/lucene/geo3d/GeoOutsideDistance.java |    55 -
 .../java/org/apache/lucene/geo3d/GeoPath.java   |   797 -
 .../java/org/apache/lucene/geo3d/GeoPoint.java  |   193 -
 .../org/apache/lucene/geo3d/GeoPolygon.java     |    26 -
 .../apache/lucene/geo3d/GeoPolygonFactory.java  |   187 -
 .../org/apache/lucene/geo3d/GeoRectangle.java   |   288 -
 .../java/org/apache/lucene/geo3d/GeoShape.java  |    63 -
 .../org/apache/lucene/geo3d/GeoSizeable.java    |    40 -
 .../lucene/geo3d/GeoSouthLatitudeZone.java      |   168 -
 .../apache/lucene/geo3d/GeoSouthRectangle.java  |   259 -
 .../apache/lucene/geo3d/GeoStandardCircle.java  |   168 -
 .../geo3d/GeoWideDegenerateHorizontalLine.java  |   238 -
 .../lucene/geo3d/GeoWideLongitudeSlice.java     |   208 -
 .../lucene/geo3d/GeoWideNorthRectangle.java     |   286 -
 .../apache/lucene/geo3d/GeoWideRectangle.java   |   319 -
 .../lucene/geo3d/GeoWideSouthRectangle.java     |   284 -
 .../java/org/apache/lucene/geo3d/GeoWorld.java  |   106 -
 .../org/apache/lucene/geo3d/LatLonBounds.java   |   322 -
 .../org/apache/lucene/geo3d/LinearDistance.java |    56 -
 .../lucene/geo3d/LinearSquaredDistance.java     |    56 -
 .../org/apache/lucene/geo3d/Membership.java     |    46 -
 .../org/apache/lucene/geo3d/NormalDistance.java |    56 -
 .../lucene/geo3d/NormalSquaredDistance.java     |    56 -
 .../src/java/org/apache/lucene/geo3d/Plane.java |  1657 --
 .../org/apache/lucene/geo3d/PlanetModel.java    |   277 -
 .../lucene/geo3d/PointInGeo3DShapeQuery.java    |   204 -
 .../org/apache/lucene/geo3d/SidedPlane.java     |   175 -
 .../apache/lucene/geo3d/StandardXYZSolid.java   |   417 -
 .../src/java/org/apache/lucene/geo3d/Tools.java |    41 -
 .../java/org/apache/lucene/geo3d/Vector.java    |   378 -
 .../java/org/apache/lucene/geo3d/XYZBounds.java |   267 -
 .../java/org/apache/lucene/geo3d/XYZSolid.java  |    26 -
 .../apache/lucene/geo3d/XYZSolidFactory.java    |    67 -
 .../java/org/apache/lucene/geo3d/XYdZSolid.java |   213 -
 .../java/org/apache/lucene/geo3d/XdYZSolid.java |   212 -
 .../org/apache/lucene/geo3d/XdYdZSolid.java     |   138 -
 .../java/org/apache/lucene/geo3d/dXYZSolid.java |   216 -
 .../org/apache/lucene/geo3d/dXYdZSolid.java     |   138 -
 .../org/apache/lucene/geo3d/dXdYZSolid.java     |   138 -
 .../org/apache/lucene/geo3d/dXdYdZSolid.java    |   146 -
 .../org/apache/lucene/geo3d/package-info.java   |    21 -
 .../org/apache/lucene/spatial3d/Geo3DPoint.java |   115 +
 .../org/apache/lucene/spatial3d/Geo3DUtil.java  |    59 +
 .../spatial3d/PointInGeo3DShapeQuery.java       |   215 +
 .../lucene/spatial3d/geom/ArcDistance.java      |    56 +
 .../lucene/spatial3d/geom/BasePlanetObject.java |    57 +
 .../lucene/spatial3d/geom/BaseXYZSolid.java     |   167 +
 .../apache/lucene/spatial3d/geom/Bounds.java    |   113 +
 .../lucene/spatial3d/geom/DistanceStyle.java    |    83 +
 .../apache/lucene/spatial3d/geom/GeoArea.java   |    67 +
 .../lucene/spatial3d/geom/GeoAreaFactory.java   |    55 +
 .../apache/lucene/spatial3d/geom/GeoBBox.java   |    36 +
 .../lucene/spatial3d/geom/GeoBBoxFactory.java   |   111 +
 .../lucene/spatial3d/geom/GeoBaseBBox.java      |    72 +
 .../lucene/spatial3d/geom/GeoBaseCircle.java    |    34 +
 .../spatial3d/geom/GeoBaseDistanceShape.java    |    56 +
 .../spatial3d/geom/GeoBaseMembershipShape.java  |    56 +
 .../lucene/spatial3d/geom/GeoBasePolygon.java   |    34 +
 .../lucene/spatial3d/geom/GeoBaseShape.java     |    59 +
 .../apache/lucene/spatial3d/geom/GeoCircle.java |    25 +
 .../lucene/spatial3d/geom/GeoCircleFactory.java |    43 +
 .../geom/GeoCompositeMembershipShape.java       |   117 +
 .../spatial3d/geom/GeoCompositePolygon.java     |    31 +
 .../lucene/spatial3d/geom/GeoConvexPolygon.java |   288 +
 .../geom/GeoDegenerateHorizontalLine.java       |   215 +
 .../geom/GeoDegenerateLatitudeZone.java         |   138 +
 .../geom/GeoDegenerateLongitudeSlice.java       |   153 +
 .../spatial3d/geom/GeoDegeneratePoint.java      |   135 +
 .../geom/GeoDegenerateVerticalLine.java         |   205 +
 .../lucene/spatial3d/geom/GeoDistance.java      |    59 +
 .../lucene/spatial3d/geom/GeoDistanceShape.java |    27 +
 .../lucene/spatial3d/geom/GeoLatitudeZone.java  |   198 +
 .../spatial3d/geom/GeoLongitudeSlice.java       |   204 +
 .../spatial3d/geom/GeoMembershipShape.java      |    27 +
 .../spatial3d/geom/GeoNorthLatitudeZone.java    |   165 +
 .../spatial3d/geom/GeoNorthRectangle.java       |   263 +
 .../spatial3d/geom/GeoOutsideDistance.java      |    55 +
 .../apache/lucene/spatial3d/geom/GeoPath.java   |   797 +
 .../apache/lucene/spatial3d/geom/GeoPoint.java  |   193 +
 .../lucene/spatial3d/geom/GeoPolygon.java       |    26 +
 .../spatial3d/geom/GeoPolygonFactory.java       |   187 +
 .../lucene/spatial3d/geom/GeoRectangle.java     |   288 +
 .../apache/lucene/spatial3d/geom/GeoShape.java  |    63 +
 .../lucene/spatial3d/geom/GeoSizeable.java      |    40 +
 .../spatial3d/geom/GeoSouthLatitudeZone.java    |   168 +
 .../spatial3d/geom/GeoSouthRectangle.java       |   259 +
 .../spatial3d/geom/GeoStandardCircle.java       |   168 +
 .../geom/GeoWideDegenerateHorizontalLine.java   |   238 +
 .../spatial3d/geom/GeoWideLongitudeSlice.java   |   208 +
 .../spatial3d/geom/GeoWideNorthRectangle.java   |   286 +
 .../lucene/spatial3d/geom/GeoWideRectangle.java |   319 +
 .../spatial3d/geom/GeoWideSouthRectangle.java   |   284 +
 .../apache/lucene/spatial3d/geom/GeoWorld.java  |   106 +
 .../lucene/spatial3d/geom/LatLonBounds.java     |   322 +
 .../lucene/spatial3d/geom/LinearDistance.java   |    56 +
 .../spatial3d/geom/LinearSquaredDistance.java   |    56 +
 .../lucene/spatial3d/geom/Membership.java       |    46 +
 .../lucene/spatial3d/geom/NormalDistance.java   |    56 +
 .../spatial3d/geom/NormalSquaredDistance.java   |    56 +
 .../org/apache/lucene/spatial3d/geom/Plane.java |  1657 ++
 .../lucene/spatial3d/geom/PlanetModel.java      |   277 +
 .../lucene/spatial3d/geom/SidedPlane.java       |   175 +
 .../lucene/spatial3d/geom/StandardXYZSolid.java |   417 +
 .../org/apache/lucene/spatial3d/geom/Tools.java |    41 +
 .../apache/lucene/spatial3d/geom/Vector.java    |   378 +
 .../apache/lucene/spatial3d/geom/XYZBounds.java |   267 +
 .../apache/lucene/spatial3d/geom/XYZSolid.java  |    26 +
 .../lucene/spatial3d/geom/XYZSolidFactory.java  |    67 +
 .../apache/lucene/spatial3d/geom/XYdZSolid.java |   213 +
 .../apache/lucene/spatial3d/geom/XdYZSolid.java |   212 +
 .../lucene/spatial3d/geom/XdYdZSolid.java       |   138 +
 .../apache/lucene/spatial3d/geom/dXYZSolid.java |   216 +
 .../lucene/spatial3d/geom/dXYdZSolid.java       |   138 +
 .../lucene/spatial3d/geom/dXdYZSolid.java       |   138 +
 .../lucene/spatial3d/geom/dXdYdZSolid.java      |   146 +
 .../lucene/spatial3d/geom/package-info.java     |    22 +
 .../apache/lucene/spatial3d/package-info.java   |    21 +
 lucene/spatial3d/src/java/overview.html         |     3 +-
 .../org/apache/lucene/geo3d/GeoBBoxTest.java    |   364 -
 .../org/apache/lucene/geo3d/GeoCircleTest.java  |   415 -
 .../lucene/geo3d/GeoConvexPolygonTest.java      |    91 -
 .../org/apache/lucene/geo3d/GeoModelTest.java   |   110 -
 .../org/apache/lucene/geo3d/GeoPathTest.java    |   270 -
 .../org/apache/lucene/geo3d/GeoPolygonTest.java |   165 -
 .../test/org/apache/lucene/geo3d/PlaneTest.java |    64 -
 .../org/apache/lucene/geo3d/TestGeo3DPoint.java |   794 -
 .../org/apache/lucene/geo3d/XYZSolidTest.java   |   220 -
 .../apache/lucene/spatial3d/TestGeo3DPoint.java |   810 +
 .../lucene/spatial3d/geom/GeoBBoxTest.java      |   364 +
 .../lucene/spatial3d/geom/GeoCircleTest.java    |   410 +
 .../spatial3d/geom/GeoConvexPolygonTest.java    |    91 +
 .../lucene/spatial3d/geom/GeoModelTest.java     |   110 +
 .../lucene/spatial3d/geom/GeoPathTest.java      |   270 +
 .../lucene/spatial3d/geom/GeoPointTest.java     |    77 +
 .../lucene/spatial3d/geom/GeoPolygonTest.java   |   165 +
 .../apache/lucene/spatial3d/geom/PlaneTest.java |    64 +
 .../lucene/spatial3d/geom/XYZSolidTest.java     |   220 +
 .../search/suggest/SortedInputIterator.java     |    23 +-
 .../suggest/document/FuzzyCompletionQuery.java  |    42 +
 .../suggest/document/PrefixCompletionQuery.java |     7 +
 .../suggest/document/RegexCompletionQuery.java  |    15 +
 .../suggest/fst/FSTCompletionBuilder.java       |     5 +-
 .../lucene/search/suggest/tst/TSTLookup.java    |    46 +-
 .../search/suggest/TestInputIterator.java       |    21 +-
 .../analyzing/AnalyzingInfixSuggesterTest.java  |    21 +-
 .../analyzing/TestFreeTextSuggester.java        |     2 +-
 .../suggest/document/TestSuggestField.java      |     3 +-
 .../search/suggest/fst/BytesRefSortersTest.java |     5 +-
 .../lucene/codecs/asserting/AssertingCodec.java |     8 +-
 .../codecs/asserting/AssertingPointFormat.java  |   153 -
 .../codecs/asserting/AssertingPointsFormat.java |   276 +
 .../lucene/codecs/cranky/CrankyCodec.java       |     6 +-
 .../lucene/codecs/cranky/CrankyPointFormat.java |   175 -
 .../codecs/cranky/CrankyPointsFormat.java       |   185 +
 .../index/BaseDocValuesFormatTestCase.java      |     2 +-
 .../lucene/index/BasePointFormatTestCase.java   |   917 -
 .../lucene/index/BasePointsFormatTestCase.java  |   950 +
 .../index/BaseStoredFieldsFormatTestCase.java   |    53 +-
 .../lucene/index/MockRandomMergePolicy.java     |     2 +-
 .../org/apache/lucene/index/RandomCodec.java    |    37 +-
 .../ThreadedIndexingAndSearchingTestCase.java   |     4 +-
 .../lucene/mockfile/FilterFileChannel.java      |     2 +-
 .../apache/lucene/mockfile/FilterFileStore.java |     2 +-
 .../lucene/mockfile/FilterFileSystem.java       |     2 +-
 .../mockfile/FilterFileSystemProvider.java      |     2 +-
 .../lucene/mockfile/FilterOutputStream2.java    |     2 +-
 .../apache/lucene/search/AssertingQuery.java    |     8 +
 .../lucene/search/ShardSearchingTestBase.java   |     2 +-
 .../lucene/store/MockDirectoryWrapper.java      |     7 +-
 .../org/apache/lucene/util/LineFileDocs.java    |    58 +-
 .../org/apache/lucene/util/LuceneTestCase.java  |   119 +-
 .../java/org/apache/lucene/util/TestUtil.java   |    57 +-
 .../asserting/TestAssertingPointFormat.java     |    30 -
 .../asserting/TestAssertingPointsFormat.java    |    30 +
 lucene/tools/javadoc/ecj.javadocs.prefs         |     2 +-
 lucene/version.properties                       |     2 +-
 solr/CHANGES.txt                                |   117 +
 solr/bin/solr                                   |     5 +-
 solr/build.xml                                  |    16 +-
 solr/common-build.xml                           |     8 +-
 .../solr/analytics/util/AnalyticsParsers.java   |     9 +-
 .../clustering/carrot2/CarrotParams.java        |    10 +-
 .../clustering/carrot2/SolrResourceLocator.java |     4 +-
 .../SolrStopwordsCarrot2LexicalDataFactory.java |     6 +-
 .../solr/collection1/conf/solrconfig.xml        |     5 -
 .../carrot2/CarrotClusteringEngineTest.java     |     6 -
 .../carrot2/EchoClusteringAlgorithm.java        |     6 +-
 .../carrot2/EchoStemsClusteringAlgorithm.java   |     8 +-
 .../carrot2/EchoTokensClusteringAlgorithm.java  |     6 +-
 ...exicalResourcesCheckClusteringAlgorithm.java |     6 +-
 .../carrot2/MockClusteringAlgorithm.java        |    12 +-
 .../dataimport/EntityProcessorWrapper.java      |    12 -
 .../dataimport/TestContentStreamDataSource.java |     6 +-
 .../TestSolrEntityProcessorEndToEnd.java        |     6 +-
 .../solr/hadoop/MorphlineGoLiveMiniMRTest.java  |     1 -
 .../solr/collection1/conf/solrconfig.xml        |     8 +-
 .../test-files/solr/minimr/conf/solrconfig.xml  |     8 +-
 .../test-files/solr/mrunit/conf/solrconfig.xml  |     9 +-
 .../collection1/conf/solrconfig.xml             |     8 +-
 .../solr/solrcloud/conf/solrconfig.xml          |     8 +-
 .../UIMAUpdateRequestProcessorTest.java         |     6 +-
 solr/core/ivy.xml                               |     2 +-
 .../client/solrj/embedded/JettySolrRunner.java  |   120 +-
 .../src/java/org/apache/solr/cloud/Assign.java  |    19 +-
 .../org/apache/solr/cloud/ElectionContext.java  |   116 +-
 .../org/apache/solr/cloud/LeaderElector.java    |    10 +-
 .../cloud/LeaderInitiatedRecoveryThread.java    |     6 -
 .../java/org/apache/solr/cloud/Overseer.java    |   122 +-
 .../cloud/OverseerCollectionMessageHandler.java |   195 +-
 .../solr/cloud/OverseerNodePrioritizer.java     |     2 +-
 .../solr/cloud/OverseerTaskProcessor.java       |    14 +-
 .../solr/cloud/SizeLimitedDistributedMap.java   |     5 +-
 .../src/java/org/apache/solr/cloud/ZkCLI.java   |     4 +-
 .../org/apache/solr/cloud/ZkController.java     |   113 +-
 .../apache/solr/cloud/rule/ReplicaAssigner.java |    60 +-
 .../java/org/apache/solr/cloud/rule/Rule.java   |     4 +-
 .../solr/core/CachingDirectoryFactory.java      |     3 +-
 .../org/apache/solr/core/CoreContainer.java     |     9 +-
 .../org/apache/solr/core/CoreDescriptor.java    |     1 +
 .../java/org/apache/solr/core/NodeConfig.java   |    20 -
 .../java/org/apache/solr/core/SolrConfig.java   |     8 +-
 .../src/java/org/apache/solr/core/SolrCore.java |   168 +-
 .../java/org/apache/solr/core/SolrCores.java    |    14 +-
 .../solr/handler/CdcrReplicatorScheduler.java   |    39 +-
 .../apache/solr/handler/CdcrRequestHandler.java |     2 +-
 .../org/apache/solr/handler/IndexFetcher.java   |    13 +-
 .../solr/handler/MoreLikeThisHandler.java       |    17 -
 .../apache/solr/handler/ReplicationHandler.java |    25 +-
 .../org/apache/solr/handler/RestoreCore.java    |     6 +-
 .../org/apache/solr/handler/SchemaHandler.java  |    77 +-
 .../apache/solr/handler/SolrConfigHandler.java  |     3 +-
 .../solr/handler/admin/AdminHandlers.java       |   151 -
 .../solr/handler/admin/ClusterStatus.java       |     3 -
 .../solr/handler/admin/CollectionsHandler.java  |     6 +-
 .../solr/handler/admin/CoreAdminHandler.java    |    31 +-
 .../solr/handler/admin/CoreAdminOperation.java  |    27 +-
 .../solr/handler/admin/LukeRequestHandler.java  |    19 +-
 .../solr/handler/admin/RebalanceLeaders.java    |     2 +-
 .../handler/component/DateFacetProcessor.java   |   255 -
 .../solr/handler/component/FacetComponent.java  |    74 +-
 .../solr/handler/component/MergeStrategy.java   |    12 +-
 .../solr/handler/component/SearchHandler.java   |    13 +-
 .../component/ShardFieldSortedHitQueue.java     |    25 +-
 .../handler/component/SpatialHeatmapFacets.java |     4 +-
 .../handler/component/StatsValuesFactory.java   |    10 +-
 .../solr/handler/component/TermsComponent.java  |    30 +-
 .../solr/handler/loader/CSVLoaderBase.java      |     5 +-
 .../solr/highlight/DefaultSolrHighlighter.java  |     7 +-
 .../org/apache/solr/internal/csv/CSVParser.java |    34 +-
 .../apache/solr/internal/csv/CSVStrategy.java   |   338 +-
 .../java/org/apache/solr/parser/CharStream.java |    16 -
 .../org/apache/solr/parser/FastCharStream.java  |     8 -
 .../apache/solr/parser/SolrQueryParserBase.java |    11 +-
 .../org/apache/solr/request/IntervalFacets.java |    14 +-
 .../org/apache/solr/request/SimpleFacets.java   |    24 +-
 .../apache/solr/response/CSVResponseWriter.java |     6 +-
 .../org/apache/solr/rest/SolrSchemaRestApi.java |    56 +-
 .../solr/rest/schema/BaseFieldResource.java     |   146 -
 .../solr/rest/schema/BaseFieldTypeResource.java |    98 -
 .../schema/CopyFieldCollectionResource.java     |   198 -
 .../schema/DynamicFieldCollectionResource.java  |   207 -
 .../solr/rest/schema/DynamicFieldResource.java  |   197 -
 .../rest/schema/FieldCollectionResource.java    |   225 -
 .../apache/solr/rest/schema/FieldResource.java  |   201 -
 .../schema/FieldTypeCollectionResource.java     |   197 -
 .../solr/rest/schema/FieldTypeResource.java     |   203 -
 .../analysis/ManagedSynonymFilterFactory.java   |     1 -
 .../solr/schema/AbstractSpatialFieldType.java   |    35 +-
 .../AbstractSpatialPrefixTreeFieldType.java     |     2 +-
 .../java/org/apache/solr/schema/BBoxField.java  |     2 +-
 .../org/apache/solr/schema/DateRangeField.java  |     2 +-
 .../org/apache/solr/schema/GeoHashField.java    |     8 +-
 .../org/apache/solr/schema/IndexSchema.java     |    20 +-
 .../java/org/apache/solr/schema/LatLonType.java |     8 +-
 .../java/org/apache/solr/schema/PointType.java  |     2 +-
 .../schema/RptWithGeometrySpatialField.java     |     7 +-
 .../org/apache/solr/schema/TrieDoubleField.java |     5 +-
 .../java/org/apache/solr/schema/TrieField.java  |    95 +-
 .../org/apache/solr/schema/TrieFloatField.java  |     5 +-
 .../java/org/apache/solr/search/CursorMark.java |    11 +-
 .../solr/search/ExtendedDismaxQParser.java      |     8 +-
 .../apache/solr/search/SolrIndexSearcher.java   |    12 +-
 .../apache/solr/search/ValueSourceParser.java   |     2 +-
 .../apache/solr/search/facet/FacetModule.java   |    23 +-
 .../apache/solr/search/facet/FacetRange.java    |     6 +-
 .../solr/search/facet/UnInvertedField.java      |     9 +-
 .../distance/GeoDistValueSourceParser.java      |    10 +-
 .../function/distance/GeohashFunction.java      |     2 +-
 .../distance/GeohashHaversineFunction.java      |    10 +-
 .../distance/HaversineConstFunction.java        |     4 +-
 .../function/distance/HaversineFunction.java    |     2 +-
 .../apache/solr/search/mlt/CloudMLTQParser.java |     2 +-
 .../org/apache/solr/servlet/HttpSolrCall.java   |     3 +
 .../java/org/apache/solr/update/PeerSync.java   |    38 +-
 .../org/apache/solr/update/SolrIndexConfig.java |    12 +-
 .../apache/solr/update/UpdateShardHandler.java  |     5 -
 .../processor/DistributedUpdateProcessor.java   |     4 +-
 .../DocExpirationUpdateProcessorFactory.java    |     6 +-
 .../processor/UpdateRequestProcessorChain.java  |     6 -
 .../org/apache/solr/util/DistanceUnits.java     |     6 +-
 .../java/org/apache/solr/util/FileUtils.java    |     3 +
 .../java/org/apache/solr/util/SpatialUtils.java |    18 +-
 .../solr/collection1/conf/schema_latest.xml     |     2 +-
 .../solr/collection1/conf/solrconfig-sql.xml    |     1 -
 .../configsets/cloud-minimal/conf/schema.xml    |    32 +
 .../cloud-minimal/conf/solrconfig.xml           |    48 +
 .../solr/DistributedIntervalFacetingTest.java   |     8 +-
 .../org/apache/solr/TestDistributedSearch.java  |    32 +-
 .../org/apache/solr/TestGroupingSearch.java     |    28 +-
 .../org/apache/solr/TestRandomDVFaceting.java   |     3 -
 .../org/apache/solr/TestSolrCoreProperties.java |     5 +-
 .../core/src/test/org/apache/solr/TestTrie.java |    14 +-
 .../solr/cloud/BaseCdcrDistributedZkTest.java   |    10 +-
 .../solr/cloud/BasicDistributedZkTest.java      |    31 +-
 .../cloud/ChaosMonkeyNothingIsSafeTest.java     |     2 +-
 .../solr/cloud/ChaosMonkeyShardSplitTest.java   |     2 +-
 .../apache/solr/cloud/CollectionReloadTest.java |     2 +-
 .../cloud/CollectionTooManyReplicasTest.java    |     6 +-
 .../CollectionsAPIAsyncDistributedZkTest.java   |   174 +-
 .../solr/cloud/CollectionsAPISolrJTest.java     |   474 +
 .../solr/cloud/CollectionsAPISolrJTests.java    |   472 -
 .../apache/solr/cloud/CustomCollectionTest.java |     1 -
 .../apache/solr/cloud/DeleteReplicaTest.java    |    60 +-
 .../org/apache/solr/cloud/DeleteShardTest.java  |    82 +-
 .../org/apache/solr/cloud/ForceLeaderTest.java  |    15 +-
 .../apache/solr/cloud/HttpPartitionTest.java    |     9 +-
 .../apache/solr/cloud/LeaderElectionTest.java   |    11 +-
 .../cloud/LeaderFailoverAfterPartitionTest.java |     2 -
 .../LeaderInitiatedRecoveryOnCommitTest.java    |     4 +-
 .../apache/solr/cloud/MigrateRouteKeyTest.java  |     4 +-
 .../apache/solr/cloud/OverseerRolesTest.java    |     2 +-
 .../org/apache/solr/cloud/OverseerTest.java     |    64 +-
 .../solr/cloud/ReplicaPropertiesBase.java       |     3 -
 .../org/apache/solr/cloud/ShardSplitTest.java   |    28 +-
 .../apache/solr/cloud/SolrCloudExampleTest.java |    10 +-
 .../org/apache/solr/cloud/SyncSliceTest.java    |     1 -
 .../solr/cloud/TestCloudDeleteByQuery.java      |   244 +
 .../TestLeaderInitiatedRecoveryThread.java      |     1 -
 .../solr/cloud/TestMiniSolrCloudCluster.java    |    47 +-
 .../cloud/TestMiniSolrCloudClusterBase.java     |     3 +-
 .../cloud/TestRandomRequestDistribution.java    |     6 +-
 .../apache/solr/cloud/TestRebalanceLeaders.java |     1 -
 .../solr/cloud/TestReplicaProperties.java       |     1 -
 .../cloud/TestSizeLimitedDistributedMap.java    |    58 +
 .../cloud/TestSolrCloudWithKerberosAlt.java     |     1 +
 .../solr/cloud/UnloadDistributedZkTest.java     |    21 +-
 .../org/apache/solr/cloud/ZkControllerTest.java |     2 +-
 .../apache/solr/cloud/hdfs/StressHdfsTest.java  |     3 +-
 .../solr/cloud/overseer/ZkStateReaderTest.java  |     6 +-
 .../solr/cloud/overseer/ZkStateWriterTest.java  |    10 +-
 .../solr/core/TestImplicitCoreProperties.java   |    61 +-
 .../apache/solr/core/TestSolrConfigHandler.java |     4 +-
 .../test/org/apache/solr/core/TestSolrXml.java  |     4 -
 .../apache/solr/core/TestXIncludeConfig.java    |     4 +-
 .../solr/handler/TestReplicationHandler.java    |     7 +-
 .../handler/TestReplicationHandlerBackup.java   |     8 +-
 .../apache/solr/handler/TestRestoreCore.java    |    63 +-
 .../handler/component/StatsComponentTest.java   |    44 +-
 .../solr/index/hdfs/CheckHdfsIndexTest.java     |     2 +
 .../apache/solr/internal/csv/CSVParserTest.java |    10 +-
 .../solr/internal/csv/CSVPrinterTest.java       |     3 +-
 .../apache/solr/request/SimpleFacetsTest.java   |   134 +-
 .../org/apache/solr/request/TestFaceting.java   |   105 +-
 .../solr/request/TestIntervalFaceting.java      |     8 +-
 .../rest/schema/TestClassNameShortening.java    |     3 +-
 .../schema/TestCopyFieldCollectionResource.java |    96 +-
 .../TestDynamicFieldCollectionResource.java     |    29 -
 .../rest/schema/TestDynamicFieldResource.java   |     7 -
 .../schema/TestFieldCollectionResource.java     |    45 -
 .../solr/rest/schema/TestFieldResource.java     |    23 +-
 .../schema/TestFieldTypeCollectionResource.java |     1 +
 .../solr/rest/schema/TestFieldTypeResource.java |    17 +-
 .../TestManagedSchemaDynamicFieldResource.java  |   366 -
 .../schema/TestManagedSchemaFieldResource.java  |   369 -
 .../TestManagedSchemaFieldTypeResource.java     |   350 -
 .../schema/TestRemoveLastDynamicCopyField.java  |    80 -
 .../schema/TestSchemaSimilarityResource.java    |     1 -
 .../analysis/TestManagedStopFilterFactory.java  |     2 +-
 .../TestManagedSynonymFilterFactory.java        |    14 +-
 .../solr/schema/SpatialRPTFieldTypeTest.java    |    56 +-
 .../TestCloudManagedSchemaConcurrent.java       |     3 +-
 .../org/apache/solr/search/TestLFUCache.java    |    13 +-
 .../apache/solr/search/TestRankQueryPlugin.java |    34 +-
 .../org/apache/solr/search/TestRecovery.java    |   160 +-
 .../apache/solr/search/TestRecoveryHdfs.java    |   140 +-
 .../apache/solr/search/TestSolr4Spatial.java    |     8 +-
 .../test/org/apache/solr/search/TestSort.java   |    33 +-
 .../solr/search/facet/TestJsonFacets.java       |    30 +-
 .../function/distance/DistanceFunctionTest.java |     4 +-
 .../solr/search/join/TestScoreJoinQPScore.java  |     9 +-
 .../similarities/TestPerFieldSimilarity.java    |     1 -
 .../TestPerFieldSimilarityClassic.java          |    86 -
 .../solr/security/BasicAuthIntegrationTest.java |     2 +-
 .../apache/solr/update/CdcrUpdateLogTest.java   |    27 +-
 .../solr/update/DirectUpdateHandlerTest.java    |     2 +-
 .../update/TestDocBasedVersionConstraints.java  |    30 +-
 ...DocExpirationUpdateProcessorFactoryTest.java |    11 +-
 .../SignatureUpdateProcessorFactoryTest.java    |    12 +-
 ...atelessScriptUpdateProcessorFactoryTest.java |     4 +-
 .../UniqFieldsUpdateProcessorFactoryTest.java   |     3 +-
 .../UpdateRequestProcessorFactoryTest.java      |     8 +-
 .../org/apache/solr/util/DistanceUnitsTest.java |     2 +-
 .../example-DIH/solr/db/conf/solrconfig.xml     |    10 +-
 .../example-DIH/solr/mail/conf/solrconfig.xml   |    10 +-
 .../example-DIH/solr/rss/conf/solrconfig.xml    |    10 +-
 .../example-DIH/solr/solr/conf/solrconfig.xml   |    10 +-
 .../example-DIH/solr/tika/conf/solrconfig.xml   |    11 +-
 solr/example/files/conf/params.json             |     6 +-
 solr/example/files/conf/solrconfig.xml          |    21 +-
 solr/licenses/spatial4j-0.5.jar.sha1            |     1 -
 solr/licenses/spatial4j-0.6.jar.sha1            |     1 +
 solr/licenses/spatial4j-NOTICE.txt              |   136 +-
 .../basic_configs/conf/solrconfig.xml           |     7 +-
 .../conf/solrconfig.xml                         |    11 +-
 .../conf/solrconfig.xml                         |    12 +-
 solr/site/quickstart.mdtext                     |     2 -
 .../solr/client/solrj/impl/HttpSolrClient.java  |     5 -
 .../client/solrj/impl/LBHttpSolrClient.java     |    13 +-
 .../solr/client/solrj/io/sql/ResultSetImpl.java |     2 +-
 .../solrj/request/CollectionAdminRequest.java   |   772 +-
 .../client/solrj/request/CoreAdminRequest.java  |     8 +-
 .../solr/client/solrj/response/FacetField.java  |    26 -
 .../solr/client/solrj/response/PivotField.java  |     8 -
 .../client/solrj/response/QueryResponse.java    |    24 -
 .../solr/client/solrj/util/ClientUtils.java     |    36 -
 .../solr/common/cloud/ClosableThread.java       |    26 -
 .../apache/solr/common/cloud/SolrZkClient.java  |     7 +-
 .../apache/solr/common/cloud/ZkCmdExecutor.java |     5 -
 .../apache/solr/common/util/ExecutorUtil.java   |    59 +-
 .../apache/solr/common/util/IteratorChain.java  |    86 -
 .../apache/solr/common/util/JavaBinCodec.java   |    40 +-
 .../solrj/sampleDateFacetResponse.xml           |    81 -
 .../solrj/sampleRangeFacetResponse.xml          |    44 +
 .../solr/collection1/conf/solrconfig-sql.xml    |     1 -
 .../solrj/beans/TestDocumentObjectBinder.java   |   101 +-
 .../solr/client/solrj/io/sql/JdbcTest.java      |    15 +
 .../solr/client/solrj/request/SchemaTest.java   |     4 -
 .../request/TestCollectionAdminRequest.java     |     8 +-
 .../client/solrj/request/TestCoreAdmin.java     |     4 +-
 .../solrj/response/NoOpResponseParserTest.java  |     2 +-
 .../solrj/response/QueryResponseTest.java       |    26 +-
 .../solr/common/params/SolrParamTest.java       |    36 +-
 .../solr/common/util/IteratorChainTest.java     |   104 -
 .../solr/common/util/TestJavaBinCodec.java      |    54 +-
 .../solr/BaseDistributedSearchTestCase.java     |    32 +
 .../java/org/apache/solr/SolrTestCaseHS.java    |    13 +-
 .../java/org/apache/solr/SolrTestCaseJ4.java    |    22 +-
 .../solr/cloud/AbstractDistribZkTestBase.java   |     4 +-
 .../cloud/AbstractFullDistribZkTestBase.java    |    12 +-
 .../java/org/apache/solr/cloud/ChaosMonkey.java |    14 +-
 .../apache/solr/cloud/SolrCloudTestCase.java    |   163 +
 solr/webapp/web/index.html                      |     2 +-
 solr/webapp/web/js/angular/app.js               |    11 -
 solr/webapp/web/js/scripts/app.js               |    11 -
 1007 files changed, 70995 insertions(+), 70102 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/78154085/solr/core/src/java/org/apache/solr/core/CoreContainer.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/78154085/solr/core/src/java/org/apache/solr/handler/CdcrRequestHandler.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/78154085/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/78154085/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
----------------------------------------------------------------------
diff --cc solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
index 0fa90bc,4279864..e850796
--- a/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
@@@ -20,13 -19,16 +20,18 @@@ package org.apache.solr.handler
  import java.io.IOException;
  import java.lang.invoke.MethodHandles;
  import java.util.Arrays;
 +import java.util.Collection;
  import java.util.Collections;
+ import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
+ import java.util.Locale;
+ import java.util.Map;
  import java.util.Set;
  
+ import com.google.common.collect.ImmutableMap;
+ import com.google.common.collect.ImmutableSet;
 +import com.google.common.collect.ImmutableList;
  import org.apache.solr.cloud.ZkSolrResourceLoader;
  import org.apache.solr.common.SolrException;
  import org.apache.solr.common.util.ContentStream;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/78154085/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/78154085/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
----------------------------------------------------------------------
diff --cc solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
index abfea2c,593dac8..b12e1fb
--- a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
@@@ -76,6 -74,6 +76,7 @@@ import org.apache.solr.client.solrj.req
  import org.apache.solr.client.solrj.request.CoreAdminRequest.RequestSyncShard;
  import org.apache.solr.client.solrj.response.RequestStatusState;
  import org.apache.solr.client.solrj.util.SolrIdentifierValidator;
++import org.apache.solr.cloud.DistributedMap;
  import org.apache.solr.cloud.Overseer;
  import org.apache.solr.cloud.OverseerCollectionMessageHandler;
  import org.apache.solr.cloud.OverseerSolrResponse;
@@@ -110,6 -108,6 +111,7 @@@ import org.apache.solr.common.util.Simp
  import org.apache.solr.common.util.Utils;
  import org.apache.solr.core.CloudConfig;
  import org.apache.solr.core.CoreContainer;
++import org.apache.solr.handler.BlobHandler;
  import org.apache.solr.handler.RequestHandlerBase;
  import org.apache.solr.handler.component.ShardHandler;
  import org.apache.solr.request.SolrQueryRequest;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/78154085/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/78154085/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/78154085/solr/core/src/test/org/apache/solr/core/TestSolrConfigHandler.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/78154085/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/78154085/solr/server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml
----------------------------------------------------------------------


[02/50] [abbrv] lucene-solr git commit: SOLR-8736: schema GET operations on fields, dynamicFields, fieldTypes, copyField are reimplemented as a part of the bulk API with less details. The tests and write implementations are removed

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/rest/schema/TestRemoveLastDynamicCopyField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestRemoveLastDynamicCopyField.java b/solr/core/src/test/org/apache/solr/rest/schema/TestRemoveLastDynamicCopyField.java
deleted file mode 100644
index 4b4ddd3..0000000
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestRemoveLastDynamicCopyField.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.
- */
-package org.apache.solr.rest.schema;
-
-import java.io.File;
-import java.io.StringReader;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.solr.util.RestTestBase;
-import org.junit.After;
-import org.junit.Before;
-import org.noggit.JSONParser;
-import org.noggit.ObjectBuilder;
-
-public class TestRemoveLastDynamicCopyField extends RestTestBase {
-  private static File tmpSolrHome;
-
-  @Before
-  public void before() throws Exception {
-    tmpSolrHome = createTempDir().toFile();
-    FileUtils.copyDirectory(new File(TEST_HOME()), tmpSolrHome.getAbsoluteFile());
-
-    System.setProperty("managed.schema.mutable", "true");
-    System.setProperty("enable.update.log", "false");
-
-    createJettyAndHarness(tmpSolrHome.getAbsolutePath(), "solrconfig-managed-schema.xml", "schema-single-dynamic-copy-field.xml",
-        "/solr", true, null);
-  }
-
-  @After
-  public void after() throws Exception {
-    if (jetty != null) {
-      jetty.stop();
-      jetty = null;
-    }
-    client = null;
-    if (restTestHarness != null) {
-      restTestHarness.close();
-    }
-    restTestHarness = null;
-  }
-
-  public void test() throws Exception {
-    List copyFields = getCopyFields();
-    assertEquals("There is more than one copyField directive", 1, copyFields.size());
-    assertEquals("The copyField source is not '*'", "*", ((Map)copyFields.get(0)).get("source"));
-    assertEquals("The copyField dest is not 'text'", "text", ((Map)copyFields.get(0)).get("dest"));
-
-    String payload = "{ 'delete-copy-field': { 'source': '*', 'dest': 'text' } }";
-
-    String response = restTestHarness.post("/schema?wt=json", json(payload));
-    Map map = (Map)ObjectBuilder.getVal(new JSONParser(new StringReader(response)));
-    assertNull(response, map.get("errors"));
-    
-    assertEquals(0, getCopyFields().size());
-  }
-  
-  private List getCopyFields() throws Exception {
-    String response = restTestHarness.query("/schema?wt=json");
-    System.err.println(response);
-    Map map = (Map)ObjectBuilder.getVal(new JSONParser(new StringReader(response)));
-    return (List)((Map)map.get("schema")).get("copyFields");
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/rest/schema/TestSchemaSimilarityResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestSchemaSimilarityResource.java b/solr/core/src/test/org/apache/solr/rest/schema/TestSchemaSimilarityResource.java
index 6b7be71..2016677 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestSchemaSimilarityResource.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/TestSchemaSimilarityResource.java
@@ -24,7 +24,6 @@ public class TestSchemaSimilarityResource extends SolrRestletTestBase {
    * NOTE: schema used by parent class doesn't define a global sim, so we get the implicit default
    * which causes the FQN of the class to be returned
    * 
-   * @see TestClassNameShortening#testShortenedGlobalSimilarityStaysShortened
    */
   @Test
   public void testGetSchemaSimilarity() throws Exception {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedStopFilterFactory.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedStopFilterFactory.java b/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedStopFilterFactory.java
index 242e5b5..be8c394 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedStopFilterFactory.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedStopFilterFactory.java
@@ -140,7 +140,7 @@ public class TestManagedStopFilterFactory extends RestTestBase {
             "/response/lst[@name='error']/int[@name='code'] = '404'");
 
     // add the new field
-    assertJPut("/schema/fields/" + newFieldName, json("{'type':'managed_en'}"),
+    assertJPost("/schema/fields", "{add-field : { name :managed_en_field, type : managed_en}}",
                "/responseHeader/status==0");
 
     // make sure the new field exists now

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedSynonymFilterFactory.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedSynonymFilterFactory.java b/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedSynonymFilterFactory.java
index 9afaf6f..26fcde1 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedSynonymFilterFactory.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/analysis/TestManagedSynonymFilterFactory.java
@@ -90,8 +90,8 @@ public class TestManagedSynonymFilterFactory extends RestTestBase {
                JSONUtil.toJSON(syns),
                "/responseHeader/status==0");
     
-    assertJQ(endpoint, 
-             "/synonymMappings/managedMap/happy==['cheerful','glad','joyful']");
+    assertJQ(endpoint,
+        "/synonymMappings/managedMap/happy==['cheerful','glad','joyful']");
 
     // request to a specific mapping
     assertJQ(endpoint+"/happy", 
@@ -146,7 +146,7 @@ public class TestManagedSynonymFilterFactory extends RestTestBase {
             "/response/lst[@name='error']/int[@name='code'] = '404'");
 
     // add the new field
-    assertJPut("/schema/fields/" + newFieldName, json("{'type':'managed_en'}"),
+    assertJPost("/schema", "{ add-field :  { name: managed_en_field, type : managed_en}}",
                "/responseHeader/status==0");
 
     // make sure the new field exists now

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/schema/TestCloudManagedSchemaConcurrent.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/TestCloudManagedSchemaConcurrent.java b/solr/core/src/test/org/apache/solr/schema/TestCloudManagedSchemaConcurrent.java
index 3d0d120..0993ba1 100644
--- a/solr/core/src/test/org/apache/solr/schema/TestCloudManagedSchemaConcurrent.java
+++ b/solr/core/src/test/org/apache/solr/schema/TestCloudManagedSchemaConcurrent.java
@@ -37,11 +37,12 @@ import org.apache.solr.util.RestTestHarness;
 import org.apache.zookeeper.data.Stat;
 import org.eclipse.jetty.servlet.ServletHolder;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.restlet.ext.servlet.ServerServlet;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-
+@Ignore
 public class TestCloudManagedSchemaConcurrent extends AbstractFullDistribZkTestBase {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
   private static final String SUCCESS_XPATH = "/response/lst[@name='responseHeader']/int[@name='status'][.='0']";

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/solrj/src/test/org/apache/solr/client/solrj/request/SchemaTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/request/SchemaTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/request/SchemaTest.java
index b723abf..72051b1 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/request/SchemaTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/request/SchemaTest.java
@@ -575,10 +575,6 @@ public class SchemaTest extends RestTestBase {
     assertThat("solr.TextField", is(equalTo(newFieldTypeRepresentation.getAttributes().get("class"))));
     assertThat(analyzerDefinition.getTokenizer().get("class"),
         is(equalTo(newFieldTypeRepresentation.getAnalyzer().getTokenizer().get("class"))));
-    assertTrue(newFieldTypeRepresentation.getFields().size() == 1);
-    assertTrue(newFieldTypeRepresentation.getFields().contains(fieldName));
-    assertTrue(newFieldTypeRepresentation.getDynamicFields().size() == 1);
-    assertTrue(newFieldTypeRepresentation.getDynamicFields().contains(dynamicFieldName));
   }
 
   @Test


[16/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBBoxFactory.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBBoxFactory.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBBoxFactory.java
new file mode 100755
index 0000000..de7493e
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBBoxFactory.java
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Factory for {@link GeoBBox}.
+ *
+ * @lucene.experimental
+ */
+public class GeoBBoxFactory {
+  private GeoBBoxFactory() {
+  }
+
+  /**
+   * Create a geobbox of the right kind given the specified bounds.
+   *
+   * @param planetModel is the planet model
+   * @param topLat    is the top latitude
+   * @param bottomLat is the bottom latitude
+   * @param leftLon   is the left longitude
+   * @param rightLon  is the right longitude
+   * @return a GeoBBox corresponding to what was specified.
+   */
+  public static GeoBBox makeGeoBBox(final PlanetModel planetModel, double topLat, double bottomLat, double leftLon, double rightLon) {
+    //System.err.println("Making rectangle for topLat="+topLat*180.0/Math.PI+", bottomLat="+bottomLat*180.0/Math.PI+", leftLon="+leftLon*180.0/Math.PI+", rightlon="+rightLon*180.0/Math.PI);
+    if (topLat > Math.PI * 0.5)
+      topLat = Math.PI * 0.5;
+    if (bottomLat < -Math.PI * 0.5)
+      bottomLat = -Math.PI * 0.5;
+    if (leftLon < -Math.PI)
+      leftLon = -Math.PI;
+    if (rightLon > Math.PI)
+      rightLon = Math.PI;
+    if (Math.abs(leftLon + Math.PI) < Vector.MINIMUM_RESOLUTION && Math.abs(rightLon - Math.PI) < Vector.MINIMUM_RESOLUTION) {
+      if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION && Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION)
+        return new GeoWorld(planetModel);
+      if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION) {
+        if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION || Math.abs(topLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION)
+          return new GeoDegeneratePoint(planetModel, topLat, 0.0);
+        return new GeoDegenerateLatitudeZone(planetModel, topLat);
+      }
+      if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION)
+        return new GeoNorthLatitudeZone(planetModel, bottomLat);
+      else if (Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION)
+        return new GeoSouthLatitudeZone(planetModel, topLat);
+      return new GeoLatitudeZone(planetModel, topLat, bottomLat);
+    }
+    //System.err.println(" not latitude zone");
+    double extent = rightLon - leftLon;
+    if (extent < 0.0)
+      extent += Math.PI * 2.0;
+    if (topLat == Math.PI * 0.5 && bottomLat == -Math.PI * 0.5) {
+      if (Math.abs(leftLon - rightLon) < Vector.MINIMUM_RESOLUTION)
+        return new GeoDegenerateLongitudeSlice(planetModel, leftLon);
+
+      if (extent >= Math.PI)
+        return new GeoWideLongitudeSlice(planetModel, leftLon, rightLon);
+
+      return new GeoLongitudeSlice(planetModel, leftLon, rightLon);
+    }
+    //System.err.println(" not longitude slice");
+    if (Math.abs(leftLon - rightLon) < Vector.MINIMUM_RESOLUTION) {
+      if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION)
+        return new GeoDegeneratePoint(planetModel, topLat, leftLon);
+      return new GeoDegenerateVerticalLine(planetModel, topLat, bottomLat, leftLon);
+    }
+    //System.err.println(" not vertical line");
+    if (extent >= Math.PI) {
+      if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION) {
+        //System.err.println(" wide degenerate line");
+        return new GeoWideDegenerateHorizontalLine(planetModel, topLat, leftLon, rightLon);
+      }
+      if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION) {
+        return new GeoWideNorthRectangle(planetModel, bottomLat, leftLon, rightLon);
+      } else if (Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION) {
+        return new GeoWideSouthRectangle(planetModel, topLat, leftLon, rightLon);
+      }
+      //System.err.println(" wide rect");
+      return new GeoWideRectangle(planetModel, topLat, bottomLat, leftLon, rightLon);
+    }
+    if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION) {
+      if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION || Math.abs(topLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION) {
+        return new GeoDegeneratePoint(planetModel, topLat, 0.0);
+      }
+      //System.err.println(" horizontal line");
+      return new GeoDegenerateHorizontalLine(planetModel, topLat, leftLon, rightLon);
+    }
+    if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION) {
+      return new GeoNorthRectangle(planetModel, bottomLat, leftLon, rightLon);
+    } else if (Math.abs(bottomLat + Math.PI * 0.5) <  Vector.MINIMUM_RESOLUTION) {
+      return new GeoSouthRectangle(planetModel, topLat, leftLon, rightLon);
+    }
+    //System.err.println(" rectangle");
+    return new GeoRectangle(planetModel, topLat, bottomLat, leftLon, rightLon);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseBBox.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseBBox.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseBBox.java
new file mode 100644
index 0000000..7190cdc
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseBBox.java
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * All bounding box shapes can derive from this base class, which furnishes
+ * some common code
+ *
+ * @lucene.internal
+ */
+public abstract class GeoBaseBBox extends GeoBaseMembershipShape implements GeoBBox {
+
+  /** Construct, given planet model.
+   *@param planetModel is the planet model.
+   */
+  public GeoBaseBBox(final PlanetModel planetModel) {
+    super(planetModel);
+  }
+
+  // Signals for relationship of edge points to shape
+  
+  /** All edgepoints inside shape */
+  protected final static int ALL_INSIDE = 0;
+  /** Some edgepoints inside shape */
+  protected final static int SOME_INSIDE = 1;
+  /** No edgepoints inside shape */
+  protected final static int NONE_INSIDE = 2;
+
+  /** Determine the relationship between this BBox and the provided
+   * shape's edgepoints.
+   *@param path is the shape.
+   *@return the relationship.
+   */
+  protected int isShapeInsideBBox(final GeoShape path) {
+    final GeoPoint[] pathPoints = path.getEdgePoints();
+    boolean foundOutside = false;
+    boolean foundInside = false;
+    for (GeoPoint p : pathPoints) {
+      if (isWithin(p)) {
+        foundInside = true;
+      } else {
+        foundOutside = true;
+      }
+      if (foundInside && foundOutside) {
+        return SOME_INSIDE;
+      }
+    }
+    if (!foundInside && !foundOutside)
+      return NONE_INSIDE;
+    if (foundInside && !foundOutside)
+      return ALL_INSIDE;
+    if (foundOutside && !foundInside)
+      return NONE_INSIDE;
+    return SOME_INSIDE;
+  }
+
+}
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseCircle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseCircle.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseCircle.java
new file mode 100644
index 0000000..75219fd
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseCircle.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * GeoCircles have all the characteristics of GeoBaseDistanceShapes, plus GeoSizeable.
+ *
+ * @lucene.experimental
+ */
+public abstract class GeoBaseCircle extends GeoBaseDistanceShape implements GeoCircle {
+
+  /** Constructor.
+   *@param planetModel is the planet model to use.
+   */
+  public GeoBaseCircle(final PlanetModel planetModel) {
+    super(planetModel);
+  }
+
+}
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseDistanceShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseDistanceShape.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseDistanceShape.java
new file mode 100644
index 0000000..39dcf96
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseDistanceShape.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Distance shapes have capabilities of both geohashing and distance
+ * computation (which also includes point membership determination).
+ *
+ * @lucene.experimental
+ */
+public abstract class GeoBaseDistanceShape extends GeoBaseMembershipShape implements GeoDistanceShape {
+
+  /** Constructor.
+   *@param planetModel is the planet model to use.
+   */
+  public GeoBaseDistanceShape(final PlanetModel planetModel) {
+    super(planetModel);
+  }
+
+  @Override
+  public boolean isWithin(Vector point) {
+    return isWithin(point.x, point.y, point.z);
+  }
+
+  @Override
+  public double computeDistance(final DistanceStyle distanceStyle, final GeoPoint point) {
+    return computeDistance(distanceStyle, point.x, point.y, point.z);
+  }
+
+  @Override
+  public double computeDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    if (!isWithin(x,y,z)) {
+      return Double.MAX_VALUE;
+    }
+    return distance(distanceStyle, x, y, z);
+  }
+
+  /** Called by a {@code computeDistance} method if X/Y/Z is not within this shape. */
+  protected abstract double distance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
+
+}
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseMembershipShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseMembershipShape.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseMembershipShape.java
new file mode 100644
index 0000000..831a7c6
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseMembershipShape.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Membership shapes have capabilities of both geohashing and membership
+ * determination.  This is a useful baseclass for them.
+ *
+ * @lucene.experimental
+ */
+public abstract class GeoBaseMembershipShape extends GeoBaseShape implements GeoMembershipShape {
+
+  /** Constructor.
+   *@param planetModel is the planet model to use.
+   */
+  public GeoBaseMembershipShape(final PlanetModel planetModel) {
+    super(planetModel);
+  }
+
+  @Override
+  public boolean isWithin(Vector point) {
+    return isWithin(point.x, point.y, point.z);
+  }
+
+  @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;
+    }
+    return outsideDistance(distanceStyle, x,y,z);
+  }
+
+  /** Called by a {@code computeOutsideDistance} method if X/Y/Z is not within this shape. */
+  protected abstract double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
+
+}
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBasePolygon.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBasePolygon.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBasePolygon.java
new file mode 100644
index 0000000..ba221ae
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBasePolygon.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * GeoBasePolygon objects are the base class of most GeoPolygon objects.
+ *
+ * @lucene.experimental
+ */
+public abstract class GeoBasePolygon extends GeoBaseMembershipShape implements GeoPolygon {
+
+  /** Constructor.
+   *@param planetModel is the planet model to use.
+   */
+  public GeoBasePolygon(final PlanetModel planetModel) {
+    super(planetModel);
+  }
+
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseShape.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseShape.java
new file mode 100644
index 0000000..54896fc
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoBaseShape.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Base extended shape object.
+ *
+ * @lucene.internal
+ */
+public abstract class GeoBaseShape extends BasePlanetObject implements GeoShape {
+
+  /** Constructor.
+   *@param planetModel is the planet model to use.
+   */
+  public GeoBaseShape(final PlanetModel planetModel) {
+    super(planetModel);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    if (isWithin(planetModel.NORTH_POLE)) {
+      bounds.noTopLatitudeBound().noLongitudeBound()
+        .addPoint(planetModel.NORTH_POLE);
+    }
+    if (isWithin(planetModel.SOUTH_POLE)) {
+      bounds.noBottomLatitudeBound().noLongitudeBound()
+        .addPoint(planetModel.SOUTH_POLE);
+    }
+    if (isWithin(planetModel.MIN_X_POLE)) {
+      bounds.addPoint(planetModel.MIN_X_POLE);
+    }
+    if (isWithin(planetModel.MAX_X_POLE)) {
+      bounds.addPoint(planetModel.MAX_X_POLE);
+    }
+    if (isWithin(planetModel.MIN_Y_POLE)) {
+      bounds.addPoint(planetModel.MIN_Y_POLE);
+    }
+    if (isWithin(planetModel.MAX_Y_POLE)) {
+      bounds.addPoint(planetModel.MAX_Y_POLE);
+    }
+  }
+
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCircle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCircle.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCircle.java
new file mode 100755
index 0000000..b05dff6
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCircle.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Interface describing circular area with a center and radius.
+ *
+ * @lucene.experimental
+ */
+public interface GeoCircle extends GeoDistanceShape, GeoSizeable {
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCircleFactory.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCircleFactory.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCircleFactory.java
new file mode 100644
index 0000000..ee75179
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCircleFactory.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Class which constructs a GeoCircle representing an arbitrary circle.
+ *
+ * @lucene.experimental
+ */
+public class GeoCircleFactory {
+  private GeoCircleFactory() {
+  }
+
+  /**
+   * Create a GeoCircle of the right kind given the specified bounds.
+   * @param planetModel is the planet model.
+   * @param latitude is the center latitude.
+   * @param longitude is the center longitude.
+   * @param radius is the radius angle.
+   * @return a GeoCircle corresponding to what was specified.
+   */
+  public static GeoCircle makeGeoCircle(final PlanetModel planetModel, final double latitude, final double longitude, final double radius) {
+    if (radius < Vector.MINIMUM_RESOLUTION) {
+      return new GeoDegeneratePoint(planetModel, latitude, longitude);
+    }
+    return new GeoStandardCircle(planetModel, latitude, longitude, radius);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCompositeMembershipShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCompositeMembershipShape.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCompositeMembershipShape.java
new file mode 100755
index 0000000..9747eda
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCompositeMembershipShape.java
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * GeoComposite is a set of GeoMembershipShape's, treated as a unit.
+ *
+ * @lucene.experimental
+ */
+public class GeoCompositeMembershipShape implements GeoMembershipShape {
+  /** The list of shapes. */
+  protected final List<GeoMembershipShape> shapes = new ArrayList<GeoMembershipShape>();
+
+  /** Constructor.
+   */
+  public GeoCompositeMembershipShape() {
+  }
+
+  /**
+   * Add a shape to the composite.
+   *@param shape is the shape to add.
+   */
+  public void addShape(final GeoMembershipShape shape) {
+    shapes.add(shape);
+  }
+
+  @Override
+  public boolean isWithin(final Vector point) {
+    return isWithin(point.x, point.y, point.z);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    for (GeoMembershipShape shape : shapes) {
+      if (shape.isWithin(x, y, z))
+        return true;
+    }
+    return false;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return shapes.get(0).getEdgePoints();
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    for (GeoMembershipShape shape : shapes) {
+      if (shape.intersects(p, notablePoints, bounds))
+        return true;
+    }
+    return false;
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    for (GeoMembershipShape shape : shapes) {
+      shape.getBounds(bounds);
+    }
+  }
+
+  @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;
+
+    return super.equals(o) && shapes.equals(other.shapes);
+  }
+
+  @Override
+  public int hashCode() {
+    return super.hashCode() * 31 + shapes.hashCode();//TODO cache
+  }
+
+  @Override
+  public String toString() {
+    return "GeoCompositeMembershipShape: {" + shapes + '}';
+  }
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCompositePolygon.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCompositePolygon.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCompositePolygon.java
new file mode 100644
index 0000000..920d3fb
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoCompositePolygon.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * GeoCompositePolygon is a specific implementation of GeoMembershipShape, which implements GeoPolygon explicitly.
+ *
+ * @lucene.experimental
+ */
+public class GeoCompositePolygon extends GeoCompositeMembershipShape implements GeoPolygon {
+  /** Constructor.
+   */
+  public GeoCompositePolygon() {
+  }
+
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoConvexPolygon.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoConvexPolygon.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoConvexPolygon.java
new file mode 100755
index 0000000..fb024b6
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoConvexPolygon.java
@@ -0,0 +1,288 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+
+/**
+ * GeoConvexPolygon objects are generic building blocks of more complex structures.
+ * The only restrictions on these objects are: (1) they must be convex; (2) they must have
+ * a maximum extent no larger than PI.  Violating either one of these limits will
+ * cause the logic to fail.
+ *
+ * @lucene.experimental
+ */
+public class GeoConvexPolygon extends GeoBasePolygon {
+  /** The list of polygon points */
+  protected final List<GeoPoint> points;
+  /** A bitset describing, for each edge, whether it is internal or not */
+  protected final BitSet isInternalEdges;
+
+  /** A list of edges */
+  protected SidedPlane[] edges = null;
+  /** The set of notable points for each edge */
+  protected GeoPoint[][] notableEdgePoints = null;
+  /** A point which is on the boundary of the polygon */
+  protected GeoPoint[] edgePoints = null;
+  /** Tracking the maximum distance we go at any one time, so to be sure it's legal */
+  protected double fullDistance = 0.0;
+  /** Set to true when the polygon is complete */
+  protected boolean isDone = false;
+  
+  /**
+   * Create a convex polygon from a list of points.  The first point must be on the
+   * external edge.
+   *@param planetModel is the planet model.
+   *@param pointList is the list of points to create the polygon from.
+   */
+  public GeoConvexPolygon(final PlanetModel planetModel, final List<GeoPoint> pointList) {
+    super(planetModel);
+    this.points = pointList;
+    this.isInternalEdges = new BitSet();
+    done(false);
+  }
+
+  /**
+   * Create a convex polygon from a list of points, keeping track of which boundaries
+   * are internal.  This is used when creating a polygon as a building block for another shape.
+   *@param planetModel is the planet model.
+   *@param pointList is the set of points to create the polygon from.
+   *@param internalEdgeFlags is a bitset describing whether each edge is internal or not.
+   *@param returnEdgeInternal is true when the final return edge is an internal one.
+   */
+  public GeoConvexPolygon(final PlanetModel planetModel, final List<GeoPoint> pointList, final BitSet internalEdgeFlags,
+                          final boolean returnEdgeInternal) {
+    super(planetModel);
+    this.points = pointList;
+    this.isInternalEdges = internalEdgeFlags;
+    done(returnEdgeInternal);
+  }
+
+  /**
+   * Create a convex polygon, with a starting latitude and longitude.
+   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
+   *@param planetModel is the planet model.
+   *@param startLatitude is the latitude of the first point.
+   *@param startLongitude is the longitude of the first point.
+   */
+  public GeoConvexPolygon(final PlanetModel planetModel, final double startLatitude, final double startLongitude) {
+    super(planetModel);
+    points = new ArrayList<>();
+    isInternalEdges = new BitSet();
+    points.add(new GeoPoint(planetModel, startLatitude, startLongitude));
+  }
+
+  /**
+   * Add a point to the polygon.
+   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
+   *
+   * @param latitude       is the latitude of the next point.
+   * @param longitude      is the longitude of the next point.
+   * @param isInternalEdge is true if the edge just added with this point should be considered "internal", and not
+   *                       intersected as part of the intersects() operation.
+   */
+  public void addPoint(final double latitude, final double longitude, final boolean isInternalEdge) {
+    if (isDone)
+      throw new IllegalStateException("Can't call addPoint() if done() already called");
+    if (isInternalEdge)
+      isInternalEdges.set(points.size() - 1);
+    points.add(new GeoPoint(planetModel, latitude, longitude));
+  }
+
+  /**
+   * Finish the polygon, by connecting the last added point with the starting point.
+   *@param isInternalReturnEdge is true if the return edge (back to start) is an internal one.
+   */
+  public void done(final boolean isInternalReturnEdge) {
+    if (isDone)
+      throw new IllegalStateException("Can't call done() more than once");
+    // If fewer than 3 points, can't do it.
+    if (points.size() < 3)
+      throw new IllegalArgumentException("Polygon needs at least three points.");
+
+    if (isInternalReturnEdge)
+      isInternalEdges.set(points.size() - 1);
+
+    isDone = true;
+    
+    // Time to construct the planes.  If the polygon is truly convex, then any adjacent point
+    // to a segment can provide an interior measurement.
+    edges = new SidedPlane[points.size()];
+    notableEdgePoints = new GeoPoint[points.size()][];
+
+    for (int i = 0; i < points.size(); i++) {
+      final GeoPoint start = points.get(i);
+      final GeoPoint end = points.get(legalIndex(i + 1));
+      final double distance = start.arcDistance(end);
+      if (distance > fullDistance)
+        fullDistance = distance;
+      final GeoPoint check = points.get(legalIndex(i + 2));
+      final SidedPlane sp = new SidedPlane(check, start, end);
+      //System.out.println("Created edge "+sp+" using start="+start+" end="+end+" check="+check);
+      edges[i] = sp;
+      notableEdgePoints[i] = new GeoPoint[]{start, end};
+    }
+    createCenterPoint();
+  }
+
+  /** Compute a reasonable center point.
+   */
+  protected void createCenterPoint() {
+    // In order to naively confirm that the polygon is convex, I would need to
+    // check every edge, and verify that every point (other than the edge endpoints)
+    // is within the edge's sided plane.  This is an order n^2 operation.  That's still
+    // not wrong, though, because everything else about polygons has a similar cost.
+    for (int edgeIndex = 0; edgeIndex < edges.length; edgeIndex++) {
+      final SidedPlane edge = edges[edgeIndex];
+      for (int pointIndex = 0; pointIndex < points.size(); pointIndex++) {
+        if (pointIndex != edgeIndex && pointIndex != legalIndex(edgeIndex + 1)) {
+          if (!edge.isWithin(points.get(pointIndex)))
+            throw new IllegalArgumentException("Polygon is not convex: Point " + points.get(pointIndex) + " Edge " + edge);
+        }
+      }
+    }
+    edgePoints = new GeoPoint[]{points.get(0)};
+  }
+
+  /** Compute a legal point index from a possibly illegal one, that may have wrapped.
+   *@param index is the index.
+   *@return the normalized index.
+   */
+  protected int legalIndex(int index) {
+    while (index >= points.size())
+      index -= points.size();
+    return index;
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    for (final SidedPlane edge : edges) {
+      if (!edge.isWithin(x, y, z))
+        return false;
+    }
+    return true;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    //System.err.println("Checking for polygon intersection with plane "+p+"...");
+    for (int edgeIndex = 0; edgeIndex < edges.length; edgeIndex++) {
+      final SidedPlane edge = edges[edgeIndex];
+      final GeoPoint[] points = this.notableEdgePoints[edgeIndex];
+      if (!isInternalEdges.get(edgeIndex)) {
+        //System.err.println(" non-internal edge "+edge);
+        // Edges flagged as 'internal only' are excluded from the matching
+        // Construct boundaries
+        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];
+          }
+        }
+        if (edge.intersects(planetModel, p, notablePoints, points, bounds, membershipBounds)) {
+          //System.err.println(" intersects!");
+          return true;
+        }
+      }
+    }
+    //System.err.println(" no intersection");
+    return false;
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+
+    // Add all the points
+    for (final GeoPoint point : points) {
+      bounds.addPoint(point);
+    }
+
+    // Add planes with membership.
+    for (int edgeIndex = 0; edgeIndex < edges.length; edgeIndex++) {
+      final SidedPlane edge = edges[edgeIndex];
+      // Construct boundaries
+      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];
+        }
+      }
+      bounds.addPlane(planetModel, edge, membershipBounds);
+    }
+  }
+
+  @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;
+    GeoConvexPolygon other = (GeoConvexPolygon) o;
+    if (!super.equals(other))
+      return false;
+    if (!other.isInternalEdges.equals(isInternalEdges))
+      return false;
+    return (other.points.equals(points));
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + points.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoConvexPolygon: {planetmodel=" + planetModel + ", points=" + points + "}";
+  }
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateHorizontalLine.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateHorizontalLine.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateHorizontalLine.java
new file mode 100644
index 0000000..b7de0c2
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateHorizontalLine.java
@@ -0,0 +1,215 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Degenerate bounding box limited on two sides (left lon, right lon).
+ * The left-right maximum extent for this shape is PI; for anything larger, use
+ * GeoWideDegenerateHorizontalLine.
+ *
+ * @lucene.internal
+ */
+public class GeoDegenerateHorizontalLine extends GeoBaseBBox {
+  /** Latitude of horizontal line */
+  protected final double latitude;
+  /** Left bounding longitude of line */
+  protected final double leftLon;
+  /** Right bounding longitude of line */
+  protected final double rightLon;
+
+  /** Left hand endpoint of line */
+  protected final GeoPoint LHC;
+  /** Right hand endpoint of line */
+  protected final GeoPoint RHC;
+
+  /** The plane describing the line */
+  protected final Plane plane;
+  /** The left side end plane */
+  protected final SidedPlane leftPlane;
+  /** The right side end plane */
+  protected final SidedPlane rightPlane;
+
+  /** Notable points for the line */
+  protected final GeoPoint[] planePoints;
+
+  /** Center of line */
+  protected final GeoPoint centerPoint;
+  /** A point that's on the line */
+  protected final GeoPoint[] edgePoints;
+
+  /**
+   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
+   *@param planetModel is the planet model.
+   *@param latitude is the latitude of the line.
+   *@param leftLon is the left end longitude.
+   *@param rightLon is the right end longitude.
+   */
+  public GeoDegenerateHorizontalLine(final PlanetModel planetModel, final double latitude, final double leftLon, double rightLon) {
+    super(planetModel);
+    // Argument checking
+    if (latitude > Math.PI * 0.5 || latitude < -Math.PI * 0.5)
+      throw new IllegalArgumentException("Latitude out of range");
+    if (leftLon < -Math.PI || leftLon > Math.PI)
+      throw new IllegalArgumentException("Left longitude out of range");
+    if (rightLon < -Math.PI || rightLon > Math.PI)
+      throw new IllegalArgumentException("Right longitude out of range");
+    double extent = rightLon - leftLon;
+    if (extent < 0.0) {
+      extent += 2.0 * Math.PI;
+    }
+    if (extent > Math.PI)
+      throw new IllegalArgumentException("Width of rectangle too great");
+
+    this.latitude = latitude;
+    this.leftLon = leftLon;
+    this.rightLon = rightLon;
+
+    final double sinLatitude = Math.sin(latitude);
+    final double cosLatitude = Math.cos(latitude);
+    final double sinLeftLon = Math.sin(leftLon);
+    final double cosLeftLon = Math.cos(leftLon);
+    final double sinRightLon = Math.sin(rightLon);
+    final double cosRightLon = Math.cos(rightLon);
+
+    // Now build the two points
+    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);
+
+    // Normalize
+    while (leftLon > rightLon) {
+      rightLon += Math.PI * 2.0;
+    }
+    final double middleLon = (leftLon + rightLon) * 0.5;
+    final double sinMiddleLon = Math.sin(middleLon);
+    final double cosMiddleLon = Math.cos(middleLon);
+
+    this.centerPoint = new GeoPoint(planetModel, sinLatitude, sinMiddleLon, cosLatitude, cosMiddleLon);
+    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
+    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
+
+    this.planePoints = new GeoPoint[]{LHC, RHC};
+
+    this.edgePoints = new GeoPoint[]{centerPoint};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    double newTopLat = latitude + angle;
+    double newBottomLat = latitude - angle;
+    // Figuring out when we escalate to a special case requires some prefiguring
+    double currentLonSpan = rightLon - leftLon;
+    if (currentLonSpan < 0.0)
+      currentLonSpan += Math.PI * 2.0;
+    double newLeftLon = leftLon - angle;
+    double newRightLon = rightLon + angle;
+    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
+      newLeftLon = -Math.PI;
+      newRightLon = Math.PI;
+    }
+    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return plane.evaluateIsZero(x, y, z) &&
+        leftPlane.isWithin(x, y, z) &&
+        rightPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public double getRadius() {
+    double topAngle = centerPoint.arcDistance(RHC);
+    double bottomAngle = centerPoint.arcDistance(LHC);
+    return Math.max(topAngle, bottomAngle);
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    return centerPoint;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    return p.intersects(planetModel, plane, notablePoints, planePoints, bounds, leftPlane, rightPlane);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds.addHorizontalPlane(planetModel, latitude, plane, leftPlane, rightPlane)
+      .addPoint(LHC).addPoint(RHC);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    //System.err.println("getting relationship between "+this+" and "+path);
+    if (path.intersects(plane, planePoints, leftPlane, rightPlane)) {
+      //System.err.println(" overlaps");
+      return OVERLAPS;
+    }
+
+    if (path.isWithin(centerPoint)) {
+      //System.err.println(" contains");
+      return CONTAINS;
+    }
+
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @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;
+    GeoDegenerateHorizontalLine other = (GeoDegenerateHorizontalLine) o;
+    return super.equals(other) && other.LHC.equals(LHC) && other.RHC.equals(RHC);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + LHC.hashCode();
+    result = 31 * result + RHC.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoDegenerateHorizontalLine: {planetmodel="+planetModel+", latitude=" + latitude + "(" + latitude * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightLon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
+  }
+}
+  
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateLatitudeZone.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateLatitudeZone.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateLatitudeZone.java
new file mode 100644
index 0000000..e794123
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateLatitudeZone.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * This GeoBBox represents an area rectangle of one specific latitude with
+ * no longitude bounds.
+ *
+ * @lucene.internal
+ */
+public class GeoDegenerateLatitudeZone extends GeoBaseBBox {
+  /** The latitude */
+  protected final double latitude;
+  /** Sine of the latitude */
+  protected final double sinLatitude;
+  /** Plane describing the latitude zone */
+  protected final Plane plane;
+  /** A point on the world that's also on the zone */
+  protected final GeoPoint interiorPoint;
+  /** An array consisting of the interiorPoint */
+  protected final GeoPoint[] edgePoints;
+  /** No notable points */
+  protected final static GeoPoint[] planePoints = new GeoPoint[0];
+
+  /** Constructor.
+   *@param planetModel is the planet model to use.
+   *@param latitude is the latitude of the latitude zone.
+   */
+  public GeoDegenerateLatitudeZone(final PlanetModel planetModel, final double latitude) {
+    super(planetModel);
+    this.latitude = latitude;
+
+    this.sinLatitude = Math.sin(latitude);
+    double cosLatitude = Math.cos(latitude);
+    this.plane = new Plane(planetModel, sinLatitude);
+    // Compute an interior point.
+    interiorPoint = new GeoPoint(planetModel, sinLatitude, 0.0, cosLatitude, 1.0);
+    edgePoints = new GeoPoint[]{interiorPoint};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    double newTopLat = latitude + angle;
+    double newBottomLat = latitude - angle;
+    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, -Math.PI, Math.PI);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return Math.abs(z - this.sinLatitude) < 1e-10;
+  }
+
+  @Override
+  public double getRadius() {
+    return Math.PI;
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    // Totally arbitrary
+    return interiorPoint;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    return p.intersects(planetModel, plane, notablePoints, planePoints, bounds);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds.noLongitudeBound()
+      .addHorizontalPlane(planetModel, latitude, plane);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    // 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.
+    //System.out.println("Got here! latitude="+latitude+" path="+path);
+
+    if (path.intersects(plane, planePoints)) {
+      return OVERLAPS;
+    }
+
+    if (path.isWithin(interiorPoint)) {
+      return CONTAINS;
+    }
+
+    return DISJOINT;
+  }
+
+  @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;
+    GeoDegenerateLatitudeZone other = (GeoDegenerateLatitudeZone) o;
+    return super.equals(other) && other.latitude == latitude;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    long temp = Double.doubleToLongBits(latitude);
+    result = 31 * result + (int) (temp ^ (temp >>> 32));
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoDegenerateLatitudeZone: {planetmodel="+planetModel+", lat=" + latitude + "(" + latitude * 180.0 / Math.PI + ")}";
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateLongitudeSlice.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateLongitudeSlice.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateLongitudeSlice.java
new file mode 100644
index 0000000..0bb7b90
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateLongitudeSlice.java
@@ -0,0 +1,153 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Degenerate longitude slice.
+ *
+ * @lucene.internal
+ */
+public class GeoDegenerateLongitudeSlice extends GeoBaseBBox {
+  /** The longitude of the slice */
+  protected final double longitude;
+
+  /** The bounding plane for the slice (through both poles, perpendicular to the slice) */
+  protected final SidedPlane boundingPlane;
+  /** The plane of the slice */
+  protected final Plane plane;
+  /** A point on the slice */
+  protected final GeoPoint interiorPoint;
+  /** An array consisting of the one point chosen on the slice */
+  protected final GeoPoint[] edgePoints;
+  /** Notable points for the slice (north and south poles) */
+  protected final GeoPoint[] planePoints;
+
+  /**
+   * Accepts only values in the following ranges: lon: {@code -PI -> PI}
+   */
+  public GeoDegenerateLongitudeSlice(final PlanetModel planetModel, final double longitude) {
+    super(planetModel);
+    // Argument checking
+    if (longitude < -Math.PI || longitude > Math.PI)
+      throw new IllegalArgumentException("Longitude out of range");
+    this.longitude = longitude;
+
+    final double sinLongitude = Math.sin(longitude);
+    final double cosLongitude = Math.cos(longitude);
+
+    this.plane = new Plane(cosLongitude, sinLongitude);
+    // We need a bounding plane too, which is perpendicular to the longitude plane and sided so that the point (0.0, longitude) is inside.
+    this.interiorPoint = new GeoPoint(planetModel, 0.0, sinLongitude, 1.0, cosLongitude);
+    this.boundingPlane = new SidedPlane(interiorPoint, -sinLongitude, cosLongitude);
+    this.edgePoints = new GeoPoint[]{interiorPoint};
+    this.planePoints = new GeoPoint[]{planetModel.NORTH_POLE, planetModel.SOUTH_POLE};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    // Figuring out when we escalate to a special case requires some prefiguring
+    double newLeftLon = longitude - angle;
+    double newRightLon = longitude + angle;
+    double currentLonSpan = 2.0 * angle;
+    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
+      newLeftLon = -Math.PI;
+      newRightLon = Math.PI;
+    }
+    return GeoBBoxFactory.makeGeoBBox(planetModel, Math.PI * 0.5, -Math.PI * 0.5, newLeftLon, newRightLon);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return plane.evaluateIsZero(x, y, z) &&
+        boundingPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public double getRadius() {
+    return Math.PI * 0.5;
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    return interiorPoint;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    return p.intersects(planetModel, plane, notablePoints, planePoints, bounds, boundingPlane);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds
+      .addVerticalPlane(planetModel, longitude, plane, boundingPlane)
+      .addPoint(planetModel.NORTH_POLE).addPoint(planetModel.SOUTH_POLE);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    // Look for intersections.
+    if (path.intersects(plane, planePoints, boundingPlane))
+      return OVERLAPS;
+
+    if (path.isWithin(interiorPoint))
+      return CONTAINS;
+
+    return DISJOINT;
+  }
+
+  @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;
+    GeoDegenerateLongitudeSlice other = (GeoDegenerateLongitudeSlice) o;
+    return super.equals(other) && other.longitude == longitude;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    long temp = Double.doubleToLongBits(longitude);
+    result = result * 31 + (int) (temp ^ (temp >>> 32));
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoDegenerateLongitudeSlice: {planetmodel="+planetModel+", longitude=" + longitude + "(" + longitude * 180.0 / Math.PI + ")}";
+  }
+}
+  
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePoint.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePoint.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePoint.java
new file mode 100644
index 0000000..fcd2037
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegeneratePoint.java
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+    
+/**
+ * This class represents a degenerate point bounding box.
+ * It is not a simple GeoPoint because we must have the latitude and longitude.
+ *
+ * @lucene.internal
+ */
+public class GeoDegeneratePoint extends GeoPoint implements GeoBBox, GeoCircle {
+  /** Current planet model, since we don't extend BasePlanetObject */
+  protected final PlanetModel planetModel;
+  /** Edge point is an area containing just this */
+  protected final GeoPoint[] edgePoints;
+
+  /** Constructor.
+   *@param planetModel is the planet model to use.
+   *@param lat is the latitude.
+   *@param lon is the longitude.
+   */
+  public GeoDegeneratePoint(final PlanetModel planetModel, final double lat, final double lon) {
+    super(planetModel, lat, lon);
+    this.planetModel = planetModel;
+    this.edgePoints = new GeoPoint[]{this};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    final double newTopLat = latitude + angle;
+    final double newBottomLat = latitude - angle;
+    final double newLeftLon = longitude - angle;
+    final double newRightLon = longitude + angle;
+    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane plane, final GeoPoint[] notablePoints, final Membership... bounds) {
+    // If not on the plane, no intersection
+    if (!plane.evaluateIsZero(this))
+      return false;
+
+    for (Membership m : bounds) {
+      if (!m.isWithin(this))
+        return false;
+    }
+    return true;
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    bounds.addPoint(this);
+  }
+
+  @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))
+      return false;
+    GeoDegeneratePoint other = (GeoDegeneratePoint) o;
+    return super.equals(other) && other.latitude == latitude && other.longitude == longitude;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoDegeneratePoint: {planetmodel="+planetModel+", lat=" + latitude + "(" + latitude * 180.0 / Math.PI + "), lon=" + longitude + "(" + longitude * 180.0 / Math.PI + ")}";
+  }
+
+  @Override
+  public boolean isWithin(final Vector point) {
+    return isWithin(point.x, point.y, point.z);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return x == this.x && y == this.y && z == this.z;
+  }
+
+  @Override
+  public double getRadius() {
+    return 0.0;
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    return this;
+  }
+
+  @Override
+  public int getRelationship(final GeoShape shape) {
+    if (shape.isWithin(this)) {
+      //System.err.println("Degenerate point "+this+" is WITHIN shape "+shape);
+      return CONTAINS;
+    }
+
+    //System.err.println("Degenerate point "+this+" is NOT within shape "+shape);
+    return DISJOINT;
+  }
+
+  @Override
+  public double computeDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    if (isWithin(x,y,z))
+      return 0.0;
+    return Double.MAX_VALUE;
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateVerticalLine.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateVerticalLine.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateVerticalLine.java
new file mode 100644
index 0000000..dff53b4
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDegenerateVerticalLine.java
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Degenerate bounding box limited on two sides (top lat, bottom lat).
+ *
+ * @lucene.internal
+ */
+public class GeoDegenerateVerticalLine extends GeoBaseBBox {
+  /** Top latitude of the vertical line */
+  protected final double topLat;
+  /** Bottom latitude of the vertical line */
+  protected final double bottomLat;
+  /** Longitude of the vertical line */
+  protected final double longitude;
+
+  /** Point at the upper end of the vertical line */
+  protected final GeoPoint UHC;
+  /** Point at the lower end of the vertical line */
+  protected final GeoPoint LHC;
+
+  /** Top end cutoff plane */
+  protected final SidedPlane topPlane;
+  /** Bottom end cutoff plane */
+  protected final SidedPlane bottomPlane;
+  /** Back-side cutoff plane */
+  protected final SidedPlane boundingPlane;
+  /** The vertical line plane */
+  protected final Plane plane;
+  /** Notable points for the line (end points) */
+  protected final GeoPoint[] planePoints;
+  /** A computed center point for the line */
+  protected final GeoPoint centerPoint;
+  /** A point that's on the line */
+  protected final GeoPoint[] edgePoints;
+
+  /**
+   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, longitude: {@code -PI -> PI}
+   */
+  public GeoDegenerateVerticalLine(final PlanetModel planetModel, final double topLat, final double bottomLat, final double longitude) {
+    super(planetModel);
+    // Argument checking
+    if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
+      throw new IllegalArgumentException("Top latitude out of range");
+    if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
+      throw new IllegalArgumentException("Bottom latitude out of range");
+    if (topLat < bottomLat)
+      throw new IllegalArgumentException("Top latitude less than bottom latitude");
+    if (longitude < -Math.PI || longitude > Math.PI)
+      throw new IllegalArgumentException("Longitude out of range");
+
+    this.topLat = topLat;
+    this.bottomLat = bottomLat;
+    this.longitude = longitude;
+
+    final double sinTopLat = Math.sin(topLat);
+    final double cosTopLat = Math.cos(topLat);
+    final double sinBottomLat = Math.sin(bottomLat);
+    final double cosBottomLat = Math.cos(bottomLat);
+    final double sinLongitude = Math.sin(longitude);
+    final double cosLongitude = Math.cos(longitude);
+
+    // Now build the two points
+    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);
+
+    final double middleLat = (topLat + bottomLat) * 0.5;
+    final double sinMiddleLat = Math.sin(middleLat);
+    final double cosMiddleLat = Math.cos(middleLat);
+
+    this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinLongitude, cosMiddleLat, cosLongitude);
+
+    this.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
+    this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
+
+    this.boundingPlane = new SidedPlane(centerPoint, -sinLongitude, cosLongitude);
+
+    this.planePoints = new GeoPoint[]{UHC, LHC};
+
+    this.edgePoints = new GeoPoint[]{centerPoint};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    final double newTopLat = topLat + angle;
+    final double newBottomLat = bottomLat - angle;
+    double newLeftLon = longitude - angle;
+    double newRightLon = longitude + angle;
+    double currentLonSpan = 2.0 * angle;
+    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
+      newLeftLon = -Math.PI;
+      newRightLon = Math.PI;
+    }
+    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return plane.evaluateIsZero(x, y, z) &&
+        boundingPlane.isWithin(x, y, z) &&
+        topPlane.isWithin(x, y, z) &&
+        bottomPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public double getRadius() {
+    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
+    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
+    // the distance to the right or left edge from the center.
+    final double topAngle = centerPoint.arcDistance(UHC);
+    final double bottomAngle = centerPoint.arcDistance(LHC);
+    return Math.max(topAngle, bottomAngle);
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    return centerPoint;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    return p.intersects(planetModel, plane, notablePoints, planePoints, bounds, boundingPlane, topPlane, bottomPlane);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds.addVerticalPlane(planetModel, longitude, plane, boundingPlane, topPlane, bottomPlane)
+      .addPoint(UHC).addPoint(LHC);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    //System.err.println(this+" relationship to "+path);
+    if (path.intersects(plane, planePoints, boundingPlane, topPlane, bottomPlane)) {
+      //System.err.println(" overlaps");
+      return OVERLAPS;
+    }
+
+    if (path.isWithin(centerPoint)) {
+      //System.err.println(" contains");
+      return CONTAINS;
+    }
+
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @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;
+    GeoDegenerateVerticalLine other = (GeoDegenerateVerticalLine) o;
+    return super.equals(other) && other.UHC.equals(UHC) && other.LHC.equals(LHC);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + UHC.hashCode();
+    result = 31 * result + LHC.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoDegenerateVerticalLine: {longitude=" + longitude + "(" + longitude * 180.0 / Math.PI + "), toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + ")}";
+  }
+}
+  
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistance.java
new file mode 100755
index 0000000..d41dd51
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistance.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * 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 {
+  
+  // 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 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 distance.
+   */
+  public default double computeDistance(final DistanceStyle distanceStyle, final GeoPoint point) {
+    return computeDistance(distanceStyle, point.x, point.y, point.z);
+  }
+
+  /**
+   * 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 distance.
+   */
+  public double computeDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistanceShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistanceShape.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistanceShape.java
new file mode 100755
index 0000000..e7b0348
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoDistanceShape.java
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Distance shapes have capabilities of both geohashing and distance
+ * computation (which also includes point membership determination).
+ *
+ * @lucene.experimental
+ */
+public interface GeoDistanceShape extends GeoMembershipShape, GeoDistance {
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoLatitudeZone.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoLatitudeZone.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoLatitudeZone.java
new file mode 100755
index 0000000..912ca32
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoLatitudeZone.java
@@ -0,0 +1,198 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * This GeoBBox represents an area rectangle limited only in latitude.
+ *
+ * @lucene.internal
+ */
+public class GeoLatitudeZone extends GeoBaseBBox {
+  /** The top latitude of the zone */
+  protected final double topLat;
+  /** The bottom latitude of the zone */
+  protected final double bottomLat;
+  /** Cosine of the top lat */
+  protected final double cosTopLat;
+  /** Cosine of the bottom lat */
+  protected final double cosBottomLat;
+  /** The top plane */
+  protected final SidedPlane topPlane;
+  /** The bottom plane */
+  protected final SidedPlane bottomPlane;
+  /** An interior point */
+  protected final GeoPoint interiorPoint;
+  /** Notable points (none) */
+  protected final static GeoPoint[] planePoints = new GeoPoint[0];
+
+  // We need two additional points because a latitude zone's boundaries don't intersect.  This is a very
+  // special case that most GeoBBox's do not have.
+  
+  /** Top boundary point */
+  protected final GeoPoint topBoundaryPoint;
+  /** Bottom boundary point */
+  protected final GeoPoint bottomBoundaryPoint;
+  /** A point on each distinct edge */
+  protected final GeoPoint[] edgePoints;
+
+  /** Constructor.
+   *@param planetModel is the planet model to use.
+   *@param topLat is the top latitude.
+   *@param bottomLat is the bottom latitude.
+   */
+  public GeoLatitudeZone(final PlanetModel planetModel, final double topLat, final double bottomLat) {
+    super(planetModel);
+    this.topLat = topLat;
+    this.bottomLat = bottomLat;
+
+    final double sinTopLat = Math.sin(topLat);
+    final double sinBottomLat = Math.sin(bottomLat);
+    this.cosTopLat = Math.cos(topLat);
+    this.cosBottomLat = Math.cos(bottomLat);
+
+    // Compute an interior point.  Pick one whose lat is between top and bottom.
+    final double middleLat = (topLat + bottomLat) * 0.5;
+    final double sinMiddleLat = Math.sin(middleLat);
+    this.interiorPoint = new GeoPoint(planetModel, sinMiddleLat, 0.0, Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 1.0);
+    this.topBoundaryPoint = new GeoPoint(planetModel, sinTopLat, 0.0, Math.sqrt(1.0 - sinTopLat * sinTopLat), 1.0);
+    this.bottomBoundaryPoint = new GeoPoint(planetModel, sinBottomLat, 0.0, Math.sqrt(1.0 - sinBottomLat * sinBottomLat), 1.0);
+
+    this.topPlane = new SidedPlane(interiorPoint, planetModel, sinTopLat);
+    this.bottomPlane = new SidedPlane(interiorPoint, planetModel, sinBottomLat);
+
+    this.edgePoints = new GeoPoint[]{topBoundaryPoint, bottomBoundaryPoint};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    final double newTopLat = topLat + angle;
+    final double newBottomLat = bottomLat - angle;
+    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, -Math.PI, Math.PI);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return topPlane.isWithin(x, y, z) &&
+        bottomPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public double getRadius() {
+    // This is a bit tricky.  I guess we should interpret this as meaning the angle of a circle that
+    // would contain all the bounding box points, when starting in the "center".
+    if (topLat > 0.0 && bottomLat < 0.0)
+      return Math.PI;
+    double maxCosLat = cosTopLat;
+    if (maxCosLat < cosBottomLat)
+      maxCosLat = cosBottomLat;
+    return maxCosLat * Math.PI;
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    // This is totally arbitrary and only a cartesian could agree with it.
+    return interiorPoint;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    return p.intersects(planetModel, topPlane, notablePoints, planePoints, bounds, bottomPlane) ||
+        p.intersects(planetModel, bottomPlane, notablePoints, planePoints, bounds, topPlane);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds.noLongitudeBound()
+      .addHorizontalPlane(planetModel, topLat, topPlane)
+      .addHorizontalPlane(planetModel, bottomLat, bottomPlane);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    final int insideRectangle = isShapeInsideBBox(path);
+    if (insideRectangle == SOME_INSIDE)
+      return OVERLAPS;
+
+    final boolean topBoundaryInsideShape = path.isWithin(topBoundaryPoint);
+    final boolean bottomBoundaryInsideShape = path.isWithin(bottomBoundaryPoint);
+
+    if (topBoundaryInsideShape && !bottomBoundaryInsideShape ||
+        !topBoundaryInsideShape && bottomBoundaryInsideShape)
+      return OVERLAPS;
+
+    final boolean insideShape = topBoundaryInsideShape && bottomBoundaryInsideShape;
+
+    if (insideRectangle == ALL_INSIDE && insideShape)
+      return OVERLAPS;
+
+    // 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(topPlane, planePoints, bottomPlane) ||
+        path.intersects(bottomPlane, planePoints, topPlane))
+      return OVERLAPS;
+
+    // There is another case for latitude zones only.  This is when the boundaries of the shape all fit
+    // within the zone, but the shape includes areas outside the zone crossing a pole.
+    // In this case, the above "overlaps" check is insufficient.  We also need to check a point on either boundary
+    // whether it is within the shape.  If both such points are within, then CONTAINS is the right answer.  If
+    // one such point is within, then OVERLAPS is the right answer.
+
+    if (insideShape)
+      return CONTAINS;
+
+    if (insideRectangle == ALL_INSIDE)
+      return WITHIN;
+
+    return DISJOINT;
+  }
+
+  @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;
+    GeoLatitudeZone other = (GeoLatitudeZone) o;
+    return super.equals(other) && other.topBoundaryPoint.equals(topBoundaryPoint) && other.bottomBoundaryPoint.equals(bottomBoundaryPoint);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + topBoundaryPoint.hashCode();
+    result = 31 * result + bottomBoundaryPoint.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoLatitudeZone: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + ")}";
+  }
+}


[47/50] [abbrv] lucene-solr git commit: remove troublesome float tests since facets only actually expose doubles

Posted by no...@apache.org.
remove troublesome float tests since facets only actually expose doubles


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

Branch: refs/heads/apiv2
Commit: 12f7ad66963a5ae784f2bd0bf8b5dbc4b3c1630e
Parents: a6c8ccb
Author: Mike McCandless <mi...@apache.org>
Authored: Tue Mar 8 17:30:30 2016 -0500
Committer: Mike McCandless <mi...@apache.org>
Committed: Tue Mar 8 17:30:30 2016 -0500

----------------------------------------------------------------------
 .../facet/range/TestRangeFacetCounts.java       | 203 -------------------
 1 file changed, 203 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/12f7ad66/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java
----------------------------------------------------------------------
diff --git a/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java b/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java
index 9f8b109..626d772 100644
--- a/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java
+++ b/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeFacetCounts.java
@@ -23,11 +23,9 @@ import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.lucene.document.DoublePoint;
-import org.apache.lucene.document.FloatPoint;
 import org.apache.lucene.document.LongPoint;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.DoubleDocValuesField;
-import org.apache.lucene.document.FloatDocValuesField;
 import org.apache.lucene.document.NumericDocValuesField;
 import org.apache.lucene.facet.DrillDownQuery;
 import org.apache.lucene.facet.DrillSideways;
@@ -52,7 +50,6 @@ import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
 import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
-import org.apache.lucene.queries.function.valuesource.FloatFieldSource;
 import org.apache.lucene.queries.function.valuesource.LongFieldSource;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.IndexSearcher;
@@ -321,37 +318,6 @@ public class TestRangeFacetCounts extends FacetTestCase {
     IOUtils.close(r, d);
   }
 
-  public void testBasicFloat() throws Exception {
-    Directory d = newDirectory();
-    RandomIndexWriter w = new RandomIndexWriter(random(), d);
-    Document doc = new Document();
-    FloatDocValuesField field = new FloatDocValuesField("field", 0.0f);
-    doc.add(field);
-    for(long l=0;l<100;l++) {
-      field.setFloatValue(l);
-      w.addDocument(doc);
-    }
-
-    IndexReader r = w.getReader();
-
-    FacetsCollector fc = new FacetsCollector();
-
-    IndexSearcher s = newSearcher(r);
-    s.search(new MatchAllDocsQuery(), fc);
-
-    Facets facets = new DoubleRangeFacetCounts("field", new FloatFieldSource("field"), fc,
-        new DoubleRange("less than 10", 0.0f, true, 10.0f, false),
-        new DoubleRange("less than or equal to 10", 0.0f, true, 10.0f, true),
-        new DoubleRange("over 90", 90.0f, false, 100.0f, false),
-        new DoubleRange("90 or above", 90.0f, true, 100.0f, false),
-        new DoubleRange("over 1000", 1000.0f, false, Double.POSITIVE_INFINITY, false));
-    
-    assertEquals("dim=field path=[] value=21 childCount=5\n  less than 10 (10)\n  less than or equal to 10 (11)\n  over 90 (9)\n  90 or above (10)\n  over 1000 (0)\n",
-                 facets.getTopChildren(10, "field").toString());
-    w.close();
-    IOUtils.close(r, d);
-  }
-
   public void testRandomLongs() throws Exception {
     Directory dir = newDirectory();
     RandomIndexWriter w = new RandomIndexWriter(random(), dir);
@@ -499,175 +465,6 @@ public class TestRangeFacetCounts extends FacetTestCase {
     IOUtils.close(r, dir);
   }
 
-  public void testRandomFloats() throws Exception {
-    Directory dir = newDirectory();
-    RandomIndexWriter w = new RandomIndexWriter(random(), dir);
-
-    int numDocs = atLeast(1000);
-    float[] values = new float[numDocs];
-    float minValue = Float.POSITIVE_INFINITY;
-    float maxValue = Float.NEGATIVE_INFINITY;
-    for(int i=0;i<numDocs;i++) {
-      Document doc = new Document();
-      float v = random().nextFloat();
-      values[i] = v;
-      doc.add(new FloatDocValuesField("field", v));
-      doc.add(new FloatPoint("field", v));
-      w.addDocument(doc);
-      minValue = Math.min(minValue, v);
-      maxValue = Math.max(maxValue, v);
-    }
-    IndexReader r = w.getReader();
-
-    IndexSearcher s = newSearcher(r, false);
-    FacetsConfig config = new FacetsConfig();
-    
-    int numIters = atLeast(10);
-    for(int iter=0;iter<numIters;iter++) {
-      if (VERBOSE) {
-        System.out.println("TEST: iter=" + iter);
-      }
-      int numRange = TestUtil.nextInt(random(), 1, 5);
-      DoubleRange[] ranges = new DoubleRange[numRange];
-      int[] expectedCounts = new int[numRange];
-      float minAcceptedValue = Float.POSITIVE_INFINITY;
-      float maxAcceptedValue = Float.NEGATIVE_INFINITY;
-      boolean[] rangeMinIncl = new boolean[numRange];
-      boolean[] rangeMaxIncl = new boolean[numRange];
-      if (VERBOSE) {
-        System.out.println("TEST: " + numRange + " ranges");
-      }
-      for(int rangeID=0;rangeID<numRange;rangeID++) {
-        double min;
-        if (rangeID > 0 && random().nextInt(10) == 7) {
-          // Use an existing boundary:
-          DoubleRange prevRange = ranges[random().nextInt(rangeID)];
-          if (random().nextBoolean()) {
-            min = prevRange.min;
-          } else {
-            min = prevRange.max;
-          }
-        } else {
-          min = random().nextDouble();
-        }
-        double max;
-        if (rangeID > 0 && random().nextInt(10) == 7) {
-          // Use an existing boundary:
-          DoubleRange prevRange = ranges[random().nextInt(rangeID)];
-          if (random().nextBoolean()) {
-            max = prevRange.min;
-          } else {
-            max = prevRange.max;
-          }
-        } else {
-          max = random().nextDouble();
-        }
-
-        if (min > max) {
-          double x = min;
-          min = max;
-          max = x;
-        }
-
-        // Must truncate to float precision so that the
-        // drill-down counts (which use NRQ.newFloatRange)
-        // are correct:
-        min = (float) min;
-        max = (float) max;
-
-        boolean minIncl;
-        boolean maxIncl;
-        if (min == max) {
-          minIncl = true;
-          maxIncl = true;
-        } else {
-          minIncl = random().nextBoolean();
-          maxIncl = random().nextBoolean();
-        }
-        rangeMinIncl[rangeID] = minIncl;
-        rangeMaxIncl[rangeID] = maxIncl;
-        ranges[rangeID] = new DoubleRange("r" + rangeID, min, minIncl, max, maxIncl);
-
-        if (VERBOSE) {
-          System.out.println("TEST:   range " + rangeID + ": " + ranges[rangeID]);
-        }
-
-        // Do "slow but hopefully correct" computation of
-        // expected count:
-        for(int i=0;i<numDocs;i++) {
-          boolean accept = true;
-          if (minIncl) {
-            accept &= values[i] >= min;
-          } else {
-            accept &= values[i] > min;
-          }
-          if (maxIncl) {
-            accept &= values[i] <= max;
-          } else {
-            accept &= values[i] < max;
-          }
-          if (VERBOSE) {
-            System.out.println("TEST:   check doc=" + i + " val=" + values[i] + " accept=" + accept);
-          }
-          if (accept) {
-            expectedCounts[rangeID]++;
-            minAcceptedValue = Math.min(minAcceptedValue, values[i]);
-            maxAcceptedValue = Math.max(maxAcceptedValue, values[i]);
-          }
-        }
-      }
-
-      FacetsCollector sfc = new FacetsCollector();
-      s.search(new MatchAllDocsQuery(), sfc);
-      Query fastMatchQuery;
-      if (random().nextBoolean()) {
-        if (random().nextBoolean()) {
-          fastMatchQuery = FloatPoint.newRangeQuery("field", minValue, maxValue);
-        } else {
-          fastMatchQuery = FloatPoint.newRangeQuery("field", minAcceptedValue, maxAcceptedValue);
-        }
-      } else {
-        fastMatchQuery = null;
-      }
-      ValueSource vs = new FloatFieldSource("field");
-      Facets facets = new DoubleRangeFacetCounts("field", vs, sfc, fastMatchQuery, ranges);
-      FacetResult result = facets.getTopChildren(10, "field");
-      assertEquals(numRange, result.labelValues.length);
-      for(int rangeID=0;rangeID<numRange;rangeID++) {
-        if (VERBOSE) {
-          System.out.println("TEST: verify range " + rangeID + " expectedCount=" + expectedCounts[rangeID]);
-        }
-        LabelAndValue subNode = result.labelValues[rangeID];
-        assertEquals("r" + rangeID, subNode.label);
-        assertEquals(expectedCounts[rangeID], subNode.value.intValue());
-
-        DoubleRange range = ranges[rangeID];
-
-        // Test drill-down:
-        DrillDownQuery ddq = new DrillDownQuery(config);
-        if (random().nextBoolean()) {
-          // We must do the nextUp/down in float space, here, because the nextUp that DoubleRange did in double space, when cast back to float,
-          // in fact does nothing!
-          float minFloat = (float) range.min;
-          if (rangeMinIncl[rangeID] == false) {
-            minFloat = Math.nextUp(minFloat);
-          }
-          float maxFloat = (float) range.max;
-          if (rangeMaxIncl[rangeID] == false) {
-            maxFloat = Math.nextAfter(maxFloat, Float.NEGATIVE_INFINITY);
-          }
-          ddq.add("field", FloatPoint.newRangeQuery("field", minFloat, maxFloat));
-        } else {
-          ddq.add("field", range.getQuery(fastMatchQuery, vs));
-        }
-        assertEquals(expectedCounts[rangeID], s.search(ddq, 10).totalHits);
-      }
-    }
-
-    w.close();
-    IOUtils.close(r, dir);
-  }
-
   public void testRandomDoubles() throws Exception {
     Directory dir = newDirectory();
     RandomIndexWriter w = new RandomIndexWriter(random(), dir);


[34/50] [abbrv] lucene-solr git commit: SOLR-8766: Remove support for admin/gettableFiles as well

Posted by no...@apache.org.
SOLR-8766: Remove support for admin/gettableFiles as well


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

Branch: refs/heads/apiv2
Commit: dcb7a882b61d679ce220de8f40045ce8b0d8830b
Parents: 4cc9ad4
Author: Varun Thacker <va...@gmail.com>
Authored: Tue Mar 8 19:11:00 2016 +0530
Committer: Varun Thacker <va...@gmail.com>
Committed: Tue Mar 8 19:32:10 2016 +0530

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  3 +-
 .../src/java/org/apache/solr/core/SolrCore.java | 51 --------------------
 2 files changed, 2 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/dcb7a882/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 02021c5..ecf8b32 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -405,7 +405,8 @@ Other Changes
 * SOLR-8736: schema GET operations on fields, dynamicFields, fieldTypes, copyField are
   reimplemented as a part of the bulk API with less details (noble)
 
-* SOLR-8766 : deprecated <admin> tag in solrconfig.xml is removed (noble)
+* SOLR-8766: Remove deprecated <admin> tag in solrconfig.xml and support for admin/gettableFiles
+  (noble, Jason Gerlowski, Varun Thacker)
 
 ==================  5.5.1 ==================
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/dcb7a882/solr/core/src/java/org/apache/solr/core/SolrCore.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java
index f4c40f8..cde878a 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -726,9 +726,6 @@ public final class SolrCore implements SolrInfoMBean, Closeable {
       reqHandlers = new RequestHandlers(this);
       reqHandlers.initHandlersFromConfig(solrConfig);
 
-      // Handle things that should eventually go away
-      initDeprecatedSupport();
-
       statsCache = initStatsCache();
 
       // cause the executor to stall so firstSearcher events won't fire
@@ -2270,54 +2267,6 @@ public final class SolrCore implements SolrInfoMBean, Closeable {
   }
 
   /**
-   * Manage anything that should be taken care of in case configs change
-   */
-  private void initDeprecatedSupport()
-  {
-    // TODO -- this should be removed in deprecation release...
-    String gettable = solrConfig.get("admin/gettableFiles", null );
-    if( gettable != null ) {
-      log.warn(
-          "solrconfig.xml uses deprecated <admin/gettableFiles>, Please "+
-          "update your config to use the ShowFileRequestHandler." );
-      if( getRequestHandler( "/admin/file" ) == null ) {
-        NamedList<String> invariants = new NamedList<>();
-
-        // Hide everything...
-        Set<String> hide = new HashSet<>();
-
-        for (String file : solrConfig.getResourceLoader().listConfigDir()) {
-          hide.add(file.toUpperCase(Locale.ROOT));
-        }
-
-        // except the "gettable" list
-        StringTokenizer st = new StringTokenizer( gettable );
-        while( st.hasMoreTokens() ) {
-          hide.remove( st.nextToken().toUpperCase(Locale.ROOT) );
-        }
-        for( String s : hide ) {
-          invariants.add( ShowFileRequestHandler.HIDDEN, s );
-        }
-
-        NamedList<Object> args = new NamedList<>();
-        args.add( "invariants", invariants );
-        ShowFileRequestHandler handler = new ShowFileRequestHandler();
-        handler.init( args );
-        reqHandlers.register("/admin/file", handler);
-
-        log.warn( "adding ShowFileRequestHandler with hidden files: "+hide );
-      }
-    }
-
-    String facetSort = solrConfig.get("//bool[@name='facet.sort']", null);
-    if (facetSort != null) {
-      log.warn(
-          "solrconfig.xml uses deprecated <bool name='facet.sort'>. Please "+
-          "update your config to use <string name='facet.sort'>.");
-    }
-  }
-
-  /**
    * Creates and initializes a RestManager based on configuration args in solrconfig.xml.
    * RestManager provides basic storage support for managed resource data, such as to
    * persist stopwords to ZooKeeper if running in SolrCloud mode.


[42/50] [abbrv] lucene-solr git commit: improve testing for sparse points

Posted by no...@apache.org.
improve testing for sparse points


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

Branch: refs/heads/apiv2
Commit: 62b3aaa526d6b883e95cf899d0fc89da11fc5e93
Parents: 56ad6e5
Author: Mike McCandless <mi...@apache.org>
Authored: Tue Mar 8 15:21:37 2016 -0500
Committer: Mike McCandless <mi...@apache.org>
Committed: Tue Mar 8 15:21:37 2016 -0500

----------------------------------------------------------------------
 .../index/TestBackwardsCompatibility.java       |  2 +-
 .../index/TestFlushByRamOrCountsPolicy.java     |  2 +-
 .../lucene/index/TestForceMergeForever.java     |  2 +-
 .../test/org/apache/lucene/index/TestNorms.java |  2 +-
 .../apache/lucene/index/TestPointValues.java    | 46 ++++++++++++++++
 .../apache/lucene/index/TestRollingUpdates.java |  2 +-
 .../org/apache/lucene/index/TestTermsEnum.java  |  2 +-
 .../lucene/store/TestNRTCachingDirectory.java   |  2 +-
 .../org/apache/lucene/util/fst/TestFSTs.java    |  2 +-
 .../analyzing/TestFreeTextSuggester.java        |  2 +-
 .../ThreadedIndexingAndSearchingTestCase.java   |  2 +-
 .../lucene/search/ShardSearchingTestBase.java   |  2 +-
 .../org/apache/lucene/util/LineFileDocs.java    | 58 +++++++++++++-------
 13 files changed, 95 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/62b3aaa5/lucene/backward-codecs/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java
----------------------------------------------------------------------
diff --git a/lucene/backward-codecs/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java b/lucene/backward-codecs/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java
index 68b32d3..bc48c7a 100644
--- a/lucene/backward-codecs/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java
+++ b/lucene/backward-codecs/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java
@@ -148,7 +148,7 @@ public class TestBackwardsCompatibility extends LuceneTestCase {
     IndexWriterConfig conf = new IndexWriterConfig(analyzer)
       .setMergePolicy(mp).setUseCompoundFile(false);
     IndexWriter writer = new IndexWriter(dir, conf);
-    LineFileDocs docs = new LineFileDocs(null, true);
+    LineFileDocs docs = new LineFileDocs(null);
     for(int i=0;i<50;i++) {
       writer.addDocument(docs.nextDoc());
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/62b3aaa5/lucene/core/src/test/org/apache/lucene/index/TestFlushByRamOrCountsPolicy.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestFlushByRamOrCountsPolicy.java b/lucene/core/src/test/org/apache/lucene/index/TestFlushByRamOrCountsPolicy.java
index 562913e..993a521 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestFlushByRamOrCountsPolicy.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestFlushByRamOrCountsPolicy.java
@@ -39,7 +39,7 @@ public class TestFlushByRamOrCountsPolicy extends LuceneTestCase {
 
   @BeforeClass
   public static void beforeClass() throws Exception {
-    lineDocFile = new LineFileDocs(random(), true);
+    lineDocFile = new LineFileDocs(random());
   }
   
   @AfterClass

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/62b3aaa5/lucene/core/src/test/org/apache/lucene/index/TestForceMergeForever.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestForceMergeForever.java b/lucene/core/src/test/org/apache/lucene/index/TestForceMergeForever.java
index 3edeef1..0379395 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestForceMergeForever.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestForceMergeForever.java
@@ -62,7 +62,7 @@ public class TestForceMergeForever extends LuceneTestCase {
     // Try to make an index that requires merging:
     w.getConfig().setMaxBufferedDocs(TestUtil.nextInt(random(), 2, 11));
     final int numStartDocs = atLeast(20);
-    final LineFileDocs docs = new LineFileDocs(random(), true);
+    final LineFileDocs docs = new LineFileDocs(random());
     for(int docIDX=0;docIDX<numStartDocs;docIDX++) {
       w.addDocument(docs.nextDoc());
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/62b3aaa5/lucene/core/src/test/org/apache/lucene/index/TestNorms.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestNorms.java b/lucene/core/src/test/org/apache/lucene/index/TestNorms.java
index 78fc872..562cefb 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestNorms.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestNorms.java
@@ -133,7 +133,7 @@ public class TestNorms extends LuceneTestCase {
     Similarity provider = new MySimProvider();
     config.setSimilarity(provider);
     RandomIndexWriter writer = new RandomIndexWriter(random, dir, config);
-    final LineFileDocs docs = new LineFileDocs(random, true);
+    final LineFileDocs docs = new LineFileDocs(random);
     int num = atLeast(100);
     for (int i = 0; i < num; i++) {
       Document doc = docs.nextDoc();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/62b3aaa5/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java b/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
index 9ced11a..55d4794 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
@@ -582,4 +582,50 @@ public class TestPointValues extends LuceneTestCase {
     w.close();
     dir.close();
   }
+
+  public void testSparsePoints() throws Exception {
+    Directory dir = newDirectory();
+    int numDocs = atLeast(1000);
+    int numFields = TestUtil.nextInt(random(), 1, 10);
+    RandomIndexWriter w = new RandomIndexWriter(random(), dir);
+    int[] fieldDocCounts = new int[numFields];
+    int[] fieldSizes = new int[numFields];
+    for(int i=0;i<numDocs;i++) {
+      Document doc = new Document();
+      for(int field=0;field<numFields;field++) {
+        String fieldName = "int" + field;
+        if (random().nextInt(100) == 17) {
+          doc.add(new IntPoint(fieldName, random().nextInt()));
+          fieldDocCounts[field]++;
+          fieldSizes[field]++;
+
+          if (random().nextInt(10) == 5) {
+            // add same field again!
+            doc.add(new IntPoint(fieldName, random().nextInt()));
+            fieldSizes[field]++;
+          }
+        }
+      }
+      w.addDocument(doc);
+    }
+
+    IndexReader r = w.getReader();
+    for(int field=0;field<numFields;field++) {
+      int docCount = 0;
+      int size = 0;
+      String fieldName = "int" + field;
+      for(LeafReaderContext ctx : r.leaves()) {
+        PointValues points = ctx.reader().getPointValues();
+        if (ctx.reader().getFieldInfos().fieldInfo(fieldName) != null) {
+          docCount += points.getDocCount(fieldName);
+          size += points.size(fieldName);
+        }
+      }
+      assertEquals(fieldDocCounts[field], docCount);
+      assertEquals(fieldSizes[field], size);
+    }
+    r.close();
+    w.close();
+    dir.close();
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/62b3aaa5/lucene/core/src/test/org/apache/lucene/index/TestRollingUpdates.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestRollingUpdates.java b/lucene/core/src/test/org/apache/lucene/index/TestRollingUpdates.java
index e02afc0..23be40b 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestRollingUpdates.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestRollingUpdates.java
@@ -40,7 +40,7 @@ public class TestRollingUpdates extends LuceneTestCase {
     Random random = new Random(random().nextLong());
     final BaseDirectoryWrapper dir = newDirectory();
     
-    final LineFileDocs docs = new LineFileDocs(random, true);
+    final LineFileDocs docs = new LineFileDocs(random);
 
     //provider.register(new MemoryCodec());
     if (random().nextBoolean()) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/62b3aaa5/lucene/core/src/test/org/apache/lucene/index/TestTermsEnum.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestTermsEnum.java b/lucene/core/src/test/org/apache/lucene/index/TestTermsEnum.java
index 3296330..aa2ca24 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestTermsEnum.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestTermsEnum.java
@@ -41,7 +41,7 @@ public class TestTermsEnum extends LuceneTestCase {
 
   public void test() throws Exception {
     Random random = new Random(random().nextLong());
-    final LineFileDocs docs = new LineFileDocs(random, true);
+    final LineFileDocs docs = new LineFileDocs(random);
     final Directory d = newDirectory();
     MockAnalyzer analyzer = new MockAnalyzer(random());
     analyzer.setMaxTokenLength(TestUtil.nextInt(random(), 1, IndexWriter.MAX_TERM_LENGTH));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/62b3aaa5/lucene/core/src/test/org/apache/lucene/store/TestNRTCachingDirectory.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/store/TestNRTCachingDirectory.java b/lucene/core/src/test/org/apache/lucene/store/TestNRTCachingDirectory.java
index dfbb7b2..227d41f 100644
--- a/lucene/core/src/test/org/apache/lucene/store/TestNRTCachingDirectory.java
+++ b/lucene/core/src/test/org/apache/lucene/store/TestNRTCachingDirectory.java
@@ -56,7 +56,7 @@ public class TestNRTCachingDirectory extends BaseDirectoryTestCase {
     analyzer.setMaxTokenLength(TestUtil.nextInt(random(), 1, IndexWriter.MAX_TERM_LENGTH));
     IndexWriterConfig conf = newIndexWriterConfig(analyzer);
     RandomIndexWriter w = new RandomIndexWriter(random(), cachedDir, conf);
-    final LineFileDocs docs = new LineFileDocs(random(), true);
+    final LineFileDocs docs = new LineFileDocs(random());
     final int numDocs = TestUtil.nextInt(random(), 100, 400);
 
     if (VERBOSE) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/62b3aaa5/lucene/core/src/test/org/apache/lucene/util/fst/TestFSTs.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/util/fst/TestFSTs.java b/lucene/core/src/test/org/apache/lucene/util/fst/TestFSTs.java
index c352938..5f01482 100644
--- a/lucene/core/src/test/org/apache/lucene/util/fst/TestFSTs.java
+++ b/lucene/core/src/test/org/apache/lucene/util/fst/TestFSTs.java
@@ -310,7 +310,7 @@ public class TestFSTs extends LuceneTestCase {
   // file, up until a doc limit
   public void testRealTerms() throws Exception {
 
-    final LineFileDocs docs = new LineFileDocs(random(), true);
+    final LineFileDocs docs = new LineFileDocs(random());
     final int numDocs = TEST_NIGHTLY ? atLeast(1000) : atLeast(100);
     MockAnalyzer analyzer = new MockAnalyzer(random());
     analyzer.setMaxTokenLength(TestUtil.nextInt(random(), 1, IndexWriter.MAX_TERM_LENGTH));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/62b3aaa5/lucene/suggest/src/test/org/apache/lucene/search/suggest/analyzing/TestFreeTextSuggester.java
----------------------------------------------------------------------
diff --git a/lucene/suggest/src/test/org/apache/lucene/search/suggest/analyzing/TestFreeTextSuggester.java b/lucene/suggest/src/test/org/apache/lucene/search/suggest/analyzing/TestFreeTextSuggester.java
index 4fd7773..b26b5332 100644
--- a/lucene/suggest/src/test/org/apache/lucene/search/suggest/analyzing/TestFreeTextSuggester.java
+++ b/lucene/suggest/src/test/org/apache/lucene/search/suggest/analyzing/TestFreeTextSuggester.java
@@ -131,7 +131,7 @@ public class TestFreeTextSuggester extends LuceneTestCase {
 
   @Ignore
   public void testWiki() throws Exception {
-    final LineFileDocs lfd = new LineFileDocs(null, "/lucenedata/enwiki/enwiki-20120502-lines-1k.txt", false);
+    final LineFileDocs lfd = new LineFileDocs(null, "/lucenedata/enwiki/enwiki-20120502-lines-1k.txt");
     // Skip header:
     lfd.nextDoc();
     Analyzer analyzer = new MockAnalyzer(random());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/62b3aaa5/lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java
index 80c3903..e79d548 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java
@@ -429,7 +429,7 @@ public abstract class ThreadedIndexingAndSearchingTestCase extends LuceneTestCas
     final long t0 = System.currentTimeMillis();
 
     Random random = new Random(random().nextLong());
-    final LineFileDocs docs = new LineFileDocs(random, true);
+    final LineFileDocs docs = new LineFileDocs(random);
     final Path tempDir = createTempDir(testName);
     dir = getDirectory(newMockFSDirectory(tempDir)); // some subclasses rely on this being MDW
     if (dir instanceof BaseDirectoryWrapper) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/62b3aaa5/lucene/test-framework/src/java/org/apache/lucene/search/ShardSearchingTestBase.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/search/ShardSearchingTestBase.java b/lucene/test-framework/src/java/org/apache/lucene/search/ShardSearchingTestBase.java
index 52c16dc..9449a72 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/search/ShardSearchingTestBase.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/search/ShardSearchingTestBase.java
@@ -552,7 +552,7 @@ public abstract class ShardSearchingTestBase extends LuceneTestCase {
     @Override
     public void run() {
       try {
-        final LineFileDocs docs = new LineFileDocs(random(), true);
+        final LineFileDocs docs = new LineFileDocs(random());
         int numDocs = 0;
         while (System.nanoTime() < endTimeNanos) {
           final int what = random().nextInt(3);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/62b3aaa5/lucene/test-framework/src/java/org/apache/lucene/util/LineFileDocs.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/util/LineFileDocs.java b/lucene/test-framework/src/java/org/apache/lucene/util/LineFileDocs.java
index 26d7cc3..8844d8f 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/util/LineFileDocs.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/util/LineFileDocs.java
@@ -33,16 +33,17 @@ import java.util.Random;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.zip.GZIPInputStream;
 
-import org.apache.lucene.document.IntPoint;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.IntPoint;
+import org.apache.lucene.document.IntPoint;
 import org.apache.lucene.document.NumericDocValuesField;
 import org.apache.lucene.document.SortedDocValuesField;
 import org.apache.lucene.document.StringField;
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexOptions;
+import org.apache.lucene.index.IndexableField;
 
 /** Minimal port of benchmark's LneDocSource +
  * DocMaker, so tests can enum docs from a line file created
@@ -53,22 +54,18 @@ public class LineFileDocs implements Closeable {
   private final static int BUFFER_SIZE = 1 << 16;     // 64K
   private final AtomicInteger id = new AtomicInteger();
   private final String path;
-  private final boolean useDocValues;
+  private final Random random;
 
   /** If forever is true, we rewind the file at EOF (repeat
    * the docs over and over) */
-  public LineFileDocs(Random random, String path, boolean useDocValues) throws IOException {
+  public LineFileDocs(Random random, String path) throws IOException {
     this.path = path;
-    this.useDocValues = useDocValues;
+    this.random = new Random(random.nextLong());
     open(random);
   }
 
   public LineFileDocs(Random random) throws IOException {
-    this(random, LuceneTestCase.TEST_LINE_DOCS_FILE, true);
-  }
-
-  public LineFileDocs(Random random, boolean useDocValues) throws IOException {
-    this(random, LuceneTestCase.TEST_LINE_DOCS_FILE, useDocValues);
+    this(random, LuceneTestCase.TEST_LINE_DOCS_FILE);
   }
 
   @Override
@@ -165,7 +162,7 @@ public class LineFileDocs implements Closeable {
     final Field idNumDV;
     final Field date;
 
-    public DocState(boolean useDocValues) {
+    public DocState() {
       doc = new Document();
       
       title = new StringField("title", "", Field.Store.NO);
@@ -192,15 +189,10 @@ public class LineFileDocs implements Closeable {
       date = new StringField("date", "", Field.Store.YES);
       doc.add(date);
 
-      if (useDocValues) {
-        titleDV = new SortedDocValuesField("titleDV", new BytesRef());
-        idNumDV = new NumericDocValuesField("docid_intDV", 0);
-        doc.add(titleDV);
-        doc.add(idNumDV);
-      } else {
-        titleDV = null;
-        idNumDV = null;
-      }
+      titleDV = new SortedDocValuesField("titleDV", new BytesRef());
+      idNumDV = new NumericDocValuesField("docid_intDV", 0);
+      doc.add(titleDV);
+      doc.add(idNumDV);
     }
   }
 
@@ -225,7 +217,7 @@ public class LineFileDocs implements Closeable {
 
     DocState docState = threadDocs.get();
     if (docState == null) {
-      docState = new DocState(useDocValues);
+      docState = new DocState();
       threadDocs.set(docState);
     }
 
@@ -252,6 +244,32 @@ public class LineFileDocs implements Closeable {
     if (docState.idNumDV != null) {
       docState.idNumDV.setLongValue(i);
     }
+
+    if (random.nextInt(5) == 4) {
+      // Make some sparse fields
+      Document doc = new Document();
+      for(IndexableField field : docState.doc) {
+        doc.add(field);
+      }
+
+      if (random.nextInt(3) == 1) {
+        int x = random.nextInt(4);
+        doc.add(new IntPoint("docLength" + x, line.length()));
+      }
+
+      if (random.nextInt(3) == 1) {
+        int x = random.nextInt(4);
+        doc.add(new IntPoint("docTitleLength" + x, title.length()));
+      }
+
+      if (random.nextInt(3) == 1) {
+        int x = random.nextInt(4);
+        doc.add(new NumericDocValuesField("docLength" + x, line.length()));
+      }
+
+      // TODO: more random sparse fields here too
+    }
+
     return docState.doc;
   }
 }


[23/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
LUCENE-7056: Geo3D package re-org


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

Branch: refs/heads/apiv2
Commit: f7f81c3284cb855136c4e468b6e1f73cf58ced4c
Parents: 3d633c6
Author: David Smiley <ds...@apache.org>
Authored: Mon Mar 7 17:29:46 2016 -0500
Committer: David Smiley <ds...@apache.org>
Committed: Mon Mar 7 20:14:19 2016 -0500

----------------------------------------------------------------------
 lucene/CHANGES.txt                              |    2 +
 .../lucene/spatial/spatial4j/Geo3dShape.java    |   12 +-
 .../lucene/spatial/spatial4j/Geo3dRptTest.java  |   14 +-
 .../Geo3dShapeRectRelationTestCase.java         |   18 +-
 .../Geo3dShapeSphereModelRectRelationTest.java  |   16 +-
 .../Geo3dShapeWGS84ModelRectRelationTest.java   |   16 +-
 .../spatial/spatial4j/geo3d/GeoPointTest.java   |   80 -
 .../org/apache/lucene/geo3d/ArcDistance.java    |   56 -
 .../apache/lucene/geo3d/BasePlanetObject.java   |   57 -
 .../org/apache/lucene/geo3d/BaseXYZSolid.java   |  167 --
 .../java/org/apache/lucene/geo3d/Bounds.java    |  113 --
 .../org/apache/lucene/geo3d/DistanceStyle.java  |   83 -
 .../org/apache/lucene/geo3d/Geo3DPoint.java     |  112 --
 .../java/org/apache/lucene/geo3d/Geo3DUtil.java |   59 -
 .../java/org/apache/lucene/geo3d/GeoArea.java   |   67 -
 .../org/apache/lucene/geo3d/GeoAreaFactory.java |   55 -
 .../java/org/apache/lucene/geo3d/GeoBBox.java   |   36 -
 .../org/apache/lucene/geo3d/GeoBBoxFactory.java |  111 --
 .../org/apache/lucene/geo3d/GeoBaseBBox.java    |   72 -
 .../org/apache/lucene/geo3d/GeoBaseCircle.java  |   34 -
 .../lucene/geo3d/GeoBaseDistanceShape.java      |   56 -
 .../lucene/geo3d/GeoBaseMembershipShape.java    |   56 -
 .../org/apache/lucene/geo3d/GeoBasePolygon.java |   34 -
 .../org/apache/lucene/geo3d/GeoBaseShape.java   |   59 -
 .../java/org/apache/lucene/geo3d/GeoCircle.java |   25 -
 .../apache/lucene/geo3d/GeoCircleFactory.java   |   43 -
 .../geo3d/GeoCompositeMembershipShape.java      |  117 --
 .../lucene/geo3d/GeoCompositePolygon.java       |   31 -
 .../apache/lucene/geo3d/GeoConvexPolygon.java   |  288 ---
 .../geo3d/GeoDegenerateHorizontalLine.java      |  215 ---
 .../lucene/geo3d/GeoDegenerateLatitudeZone.java |  138 --
 .../geo3d/GeoDegenerateLongitudeSlice.java      |  153 --
 .../apache/lucene/geo3d/GeoDegeneratePoint.java |  135 --
 .../lucene/geo3d/GeoDegenerateVerticalLine.java |  205 ---
 .../org/apache/lucene/geo3d/GeoDistance.java    |   59 -
 .../apache/lucene/geo3d/GeoDistanceShape.java   |   27 -
 .../apache/lucene/geo3d/GeoLatitudeZone.java    |  198 ---
 .../apache/lucene/geo3d/GeoLongitudeSlice.java  |  204 ---
 .../apache/lucene/geo3d/GeoMembershipShape.java |   27 -
 .../lucene/geo3d/GeoNorthLatitudeZone.java      |  165 --
 .../apache/lucene/geo3d/GeoNorthRectangle.java  |  263 ---
 .../apache/lucene/geo3d/GeoOutsideDistance.java |   55 -
 .../java/org/apache/lucene/geo3d/GeoPath.java   |  797 ---------
 .../java/org/apache/lucene/geo3d/GeoPoint.java  |  193 --
 .../org/apache/lucene/geo3d/GeoPolygon.java     |   26 -
 .../apache/lucene/geo3d/GeoPolygonFactory.java  |  187 --
 .../org/apache/lucene/geo3d/GeoRectangle.java   |  288 ---
 .../java/org/apache/lucene/geo3d/GeoShape.java  |   63 -
 .../org/apache/lucene/geo3d/GeoSizeable.java    |   40 -
 .../lucene/geo3d/GeoSouthLatitudeZone.java      |  168 --
 .../apache/lucene/geo3d/GeoSouthRectangle.java  |  259 ---
 .../apache/lucene/geo3d/GeoStandardCircle.java  |  168 --
 .../geo3d/GeoWideDegenerateHorizontalLine.java  |  238 ---
 .../lucene/geo3d/GeoWideLongitudeSlice.java     |  208 ---
 .../lucene/geo3d/GeoWideNorthRectangle.java     |  286 ---
 .../apache/lucene/geo3d/GeoWideRectangle.java   |  319 ----
 .../lucene/geo3d/GeoWideSouthRectangle.java     |  284 ---
 .../java/org/apache/lucene/geo3d/GeoWorld.java  |  106 --
 .../org/apache/lucene/geo3d/LatLonBounds.java   |  322 ----
 .../org/apache/lucene/geo3d/LinearDistance.java |   56 -
 .../lucene/geo3d/LinearSquaredDistance.java     |   56 -
 .../org/apache/lucene/geo3d/Membership.java     |   46 -
 .../org/apache/lucene/geo3d/NormalDistance.java |   56 -
 .../lucene/geo3d/NormalSquaredDistance.java     |   56 -
 .../src/java/org/apache/lucene/geo3d/Plane.java | 1657 ------------------
 .../org/apache/lucene/geo3d/PlanetModel.java    |  277 ---
 .../lucene/geo3d/PointInGeo3DShapeQuery.java    |  210 ---
 .../org/apache/lucene/geo3d/SidedPlane.java     |  175 --
 .../apache/lucene/geo3d/StandardXYZSolid.java   |  417 -----
 .../src/java/org/apache/lucene/geo3d/Tools.java |   41 -
 .../java/org/apache/lucene/geo3d/Vector.java    |  378 ----
 .../java/org/apache/lucene/geo3d/XYZBounds.java |  267 ---
 .../java/org/apache/lucene/geo3d/XYZSolid.java  |   26 -
 .../apache/lucene/geo3d/XYZSolidFactory.java    |   67 -
 .../java/org/apache/lucene/geo3d/XYdZSolid.java |  213 ---
 .../java/org/apache/lucene/geo3d/XdYZSolid.java |  212 ---
 .../org/apache/lucene/geo3d/XdYdZSolid.java     |  138 --
 .../java/org/apache/lucene/geo3d/dXYZSolid.java |  216 ---
 .../org/apache/lucene/geo3d/dXYdZSolid.java     |  138 --
 .../org/apache/lucene/geo3d/dXdYZSolid.java     |  138 --
 .../org/apache/lucene/geo3d/dXdYdZSolid.java    |  146 --
 .../org/apache/lucene/geo3d/package-info.java   |   21 -
 .../org/apache/lucene/spatial3d/Geo3DPoint.java |  114 ++
 .../org/apache/lucene/spatial3d/Geo3DUtil.java  |   59 +
 .../spatial3d/PointInGeo3DShapeQuery.java       |  215 +++
 .../lucene/spatial3d/geom/ArcDistance.java      |   56 +
 .../lucene/spatial3d/geom/BasePlanetObject.java |   57 +
 .../lucene/spatial3d/geom/BaseXYZSolid.java     |  167 ++
 .../apache/lucene/spatial3d/geom/Bounds.java    |  113 ++
 .../lucene/spatial3d/geom/DistanceStyle.java    |   83 +
 .../apache/lucene/spatial3d/geom/GeoArea.java   |   67 +
 .../lucene/spatial3d/geom/GeoAreaFactory.java   |   55 +
 .../apache/lucene/spatial3d/geom/GeoBBox.java   |   36 +
 .../lucene/spatial3d/geom/GeoBBoxFactory.java   |  111 ++
 .../lucene/spatial3d/geom/GeoBaseBBox.java      |   72 +
 .../lucene/spatial3d/geom/GeoBaseCircle.java    |   34 +
 .../spatial3d/geom/GeoBaseDistanceShape.java    |   56 +
 .../spatial3d/geom/GeoBaseMembershipShape.java  |   56 +
 .../lucene/spatial3d/geom/GeoBasePolygon.java   |   34 +
 .../lucene/spatial3d/geom/GeoBaseShape.java     |   59 +
 .../apache/lucene/spatial3d/geom/GeoCircle.java |   25 +
 .../lucene/spatial3d/geom/GeoCircleFactory.java |   43 +
 .../geom/GeoCompositeMembershipShape.java       |  117 ++
 .../spatial3d/geom/GeoCompositePolygon.java     |   31 +
 .../lucene/spatial3d/geom/GeoConvexPolygon.java |  288 +++
 .../geom/GeoDegenerateHorizontalLine.java       |  215 +++
 .../geom/GeoDegenerateLatitudeZone.java         |  138 ++
 .../geom/GeoDegenerateLongitudeSlice.java       |  153 ++
 .../spatial3d/geom/GeoDegeneratePoint.java      |  135 ++
 .../geom/GeoDegenerateVerticalLine.java         |  205 +++
 .../lucene/spatial3d/geom/GeoDistance.java      |   59 +
 .../lucene/spatial3d/geom/GeoDistanceShape.java |   27 +
 .../lucene/spatial3d/geom/GeoLatitudeZone.java  |  198 +++
 .../spatial3d/geom/GeoLongitudeSlice.java       |  204 +++
 .../spatial3d/geom/GeoMembershipShape.java      |   27 +
 .../spatial3d/geom/GeoNorthLatitudeZone.java    |  165 ++
 .../spatial3d/geom/GeoNorthRectangle.java       |  263 +++
 .../spatial3d/geom/GeoOutsideDistance.java      |   55 +
 .../apache/lucene/spatial3d/geom/GeoPath.java   |  797 +++++++++
 .../apache/lucene/spatial3d/geom/GeoPoint.java  |  193 ++
 .../lucene/spatial3d/geom/GeoPolygon.java       |   26 +
 .../spatial3d/geom/GeoPolygonFactory.java       |  187 ++
 .../lucene/spatial3d/geom/GeoRectangle.java     |  288 +++
 .../apache/lucene/spatial3d/geom/GeoShape.java  |   63 +
 .../lucene/spatial3d/geom/GeoSizeable.java      |   40 +
 .../spatial3d/geom/GeoSouthLatitudeZone.java    |  168 ++
 .../spatial3d/geom/GeoSouthRectangle.java       |  259 +++
 .../spatial3d/geom/GeoStandardCircle.java       |  168 ++
 .../geom/GeoWideDegenerateHorizontalLine.java   |  238 +++
 .../spatial3d/geom/GeoWideLongitudeSlice.java   |  208 +++
 .../spatial3d/geom/GeoWideNorthRectangle.java   |  286 +++
 .../lucene/spatial3d/geom/GeoWideRectangle.java |  319 ++++
 .../spatial3d/geom/GeoWideSouthRectangle.java   |  284 +++
 .../apache/lucene/spatial3d/geom/GeoWorld.java  |  106 ++
 .../lucene/spatial3d/geom/LatLonBounds.java     |  322 ++++
 .../lucene/spatial3d/geom/LinearDistance.java   |   56 +
 .../spatial3d/geom/LinearSquaredDistance.java   |   56 +
 .../lucene/spatial3d/geom/Membership.java       |   46 +
 .../lucene/spatial3d/geom/NormalDistance.java   |   56 +
 .../spatial3d/geom/NormalSquaredDistance.java   |   56 +
 .../org/apache/lucene/spatial3d/geom/Plane.java | 1657 ++++++++++++++++++
 .../lucene/spatial3d/geom/PlanetModel.java      |  277 +++
 .../lucene/spatial3d/geom/SidedPlane.java       |  175 ++
 .../lucene/spatial3d/geom/StandardXYZSolid.java |  417 +++++
 .../org/apache/lucene/spatial3d/geom/Tools.java |   41 +
 .../apache/lucene/spatial3d/geom/Vector.java    |  378 ++++
 .../apache/lucene/spatial3d/geom/XYZBounds.java |  267 +++
 .../apache/lucene/spatial3d/geom/XYZSolid.java  |   26 +
 .../lucene/spatial3d/geom/XYZSolidFactory.java  |   67 +
 .../apache/lucene/spatial3d/geom/XYdZSolid.java |  213 +++
 .../apache/lucene/spatial3d/geom/XdYZSolid.java |  212 +++
 .../lucene/spatial3d/geom/XdYdZSolid.java       |  138 ++
 .../apache/lucene/spatial3d/geom/dXYZSolid.java |  216 +++
 .../lucene/spatial3d/geom/dXYdZSolid.java       |  138 ++
 .../lucene/spatial3d/geom/dXdYZSolid.java       |  138 ++
 .../lucene/spatial3d/geom/dXdYdZSolid.java      |  146 ++
 .../lucene/spatial3d/geom/package-info.java     |   22 +
 .../apache/lucene/spatial3d/package-info.java   |   21 +
 lucene/spatial3d/src/java/overview.html         |    3 +-
 .../org/apache/lucene/geo3d/GeoBBoxTest.java    |  364 ----
 .../org/apache/lucene/geo3d/GeoCircleTest.java  |  415 -----
 .../lucene/geo3d/GeoConvexPolygonTest.java      |   91 -
 .../org/apache/lucene/geo3d/GeoModelTest.java   |  110 --
 .../org/apache/lucene/geo3d/GeoPathTest.java    |  270 ---
 .../org/apache/lucene/geo3d/GeoPolygonTest.java |  165 --
 .../test/org/apache/lucene/geo3d/PlaneTest.java |   64 -
 .../org/apache/lucene/geo3d/TestGeo3DPoint.java |  801 ---------
 .../org/apache/lucene/geo3d/XYZSolidTest.java   |  220 ---
 .../apache/lucene/spatial3d/TestGeo3DPoint.java |  810 +++++++++
 .../lucene/spatial3d/geom/GeoBBoxTest.java      |  364 ++++
 .../lucene/spatial3d/geom/GeoCircleTest.java    |  410 +++++
 .../spatial3d/geom/GeoConvexPolygonTest.java    |   91 +
 .../lucene/spatial3d/geom/GeoModelTest.java     |  110 ++
 .../lucene/spatial3d/geom/GeoPathTest.java      |  270 +++
 .../lucene/spatial3d/geom/GeoPointTest.java     |   77 +
 .../lucene/spatial3d/geom/GeoPolygonTest.java   |  165 ++
 .../apache/lucene/spatial3d/geom/PlaneTest.java |   64 +
 .../lucene/spatial3d/geom/XYZSolidTest.java     |  220 +++
 178 files changed, 15186 insertions(+), 15153 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/CHANGES.txt
----------------------------------------------------------------------
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 5e717d4..65281b5 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -133,6 +133,8 @@ API Changes
 * LUCENE-7072: Geo3DPoint always uses WGS84 planet model.
   (Robert Muir, Mike McCandless)
 
+* LUCENE-7056: Geo3D classes are in different packages now. (David Smiley)
+
 Optimizations
 
 * LUCENE-6891: Use prefix coding when writing points in 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial-extras/src/java/org/apache/lucene/spatial/spatial4j/Geo3dShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial-extras/src/java/org/apache/lucene/spatial/spatial4j/Geo3dShape.java b/lucene/spatial-extras/src/java/org/apache/lucene/spatial/spatial4j/Geo3dShape.java
index 518fb32..9fa6d8e 100644
--- a/lucene/spatial-extras/src/java/org/apache/lucene/spatial/spatial4j/Geo3dShape.java
+++ b/lucene/spatial-extras/src/java/org/apache/lucene/spatial/spatial4j/Geo3dShape.java
@@ -23,12 +23,12 @@ import org.locationtech.spatial4j.shape.Rectangle;
 import org.locationtech.spatial4j.shape.Shape;
 import org.locationtech.spatial4j.shape.SpatialRelation;
 import org.locationtech.spatial4j.shape.impl.RectangleImpl;
-import org.apache.lucene.geo3d.LatLonBounds;
-import org.apache.lucene.geo3d.GeoArea;
-import org.apache.lucene.geo3d.GeoAreaFactory;
-import org.apache.lucene.geo3d.GeoPoint;
-import org.apache.lucene.geo3d.GeoShape;
-import org.apache.lucene.geo3d.PlanetModel;
+import org.apache.lucene.spatial3d.geom.LatLonBounds;
+import org.apache.lucene.spatial3d.geom.GeoArea;
+import org.apache.lucene.spatial3d.geom.GeoAreaFactory;
+import org.apache.lucene.spatial3d.geom.GeoPoint;
+import org.apache.lucene.spatial3d.geom.GeoShape;
+import org.apache.lucene.spatial3d.geom.PlanetModel;
 
 /**
  * A Spatial4j Shape wrapping a {@link GeoShape} ("Geo3D") -- a 3D planar geometry based Spatial4j Shape implementation.

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dRptTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dRptTest.java b/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dRptTest.java
index d26bb29..e62b857 100644
--- a/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dRptTest.java
+++ b/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dRptTest.java
@@ -32,13 +32,13 @@ import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree;
 import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
 import org.apache.lucene.spatial.query.SpatialOperation;
 import org.apache.lucene.spatial.serialized.SerializedDVStrategy;
-import org.apache.lucene.geo3d.GeoBBoxFactory;
-import org.apache.lucene.geo3d.GeoStandardCircle;
-import org.apache.lucene.geo3d.GeoPath;
-import org.apache.lucene.geo3d.GeoPoint;
-import org.apache.lucene.geo3d.GeoPolygonFactory;
-import org.apache.lucene.geo3d.GeoShape;
-import org.apache.lucene.geo3d.PlanetModel;
+import org.apache.lucene.spatial3d.geom.GeoBBoxFactory;
+import org.apache.lucene.spatial3d.geom.GeoStandardCircle;
+import org.apache.lucene.spatial3d.geom.GeoPath;
+import org.apache.lucene.spatial3d.geom.GeoPoint;
+import org.apache.lucene.spatial3d.geom.GeoPolygonFactory;
+import org.apache.lucene.spatial3d.geom.GeoShape;
+import org.apache.lucene.spatial3d.geom.PlanetModel;
 import org.junit.Test;
 
 import static org.locationtech.spatial4j.distance.DistanceUtils.DEGREES_TO_RADIANS;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeRectRelationTestCase.java
----------------------------------------------------------------------
diff --git a/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeRectRelationTestCase.java b/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeRectRelationTestCase.java
index 134b8c7..d58985f 100644
--- a/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeRectRelationTestCase.java
+++ b/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeRectRelationTestCase.java
@@ -25,15 +25,15 @@ import org.locationtech.spatial4j.distance.DistanceUtils;
 import org.locationtech.spatial4j.shape.Circle;
 import org.locationtech.spatial4j.shape.Point;
 import org.locationtech.spatial4j.shape.RectIntersectionTestHelper;
-import org.apache.lucene.geo3d.LatLonBounds;
-import org.apache.lucene.geo3d.GeoBBox;
-import org.apache.lucene.geo3d.GeoBBoxFactory;
-import org.apache.lucene.geo3d.GeoStandardCircle;
-import org.apache.lucene.geo3d.GeoPath;
-import org.apache.lucene.geo3d.GeoPoint;
-import org.apache.lucene.geo3d.GeoPolygonFactory;
-import org.apache.lucene.geo3d.GeoShape;
-import org.apache.lucene.geo3d.PlanetModel;
+import org.apache.lucene.spatial3d.geom.LatLonBounds;
+import org.apache.lucene.spatial3d.geom.GeoBBox;
+import org.apache.lucene.spatial3d.geom.GeoBBoxFactory;
+import org.apache.lucene.spatial3d.geom.GeoStandardCircle;
+import org.apache.lucene.spatial3d.geom.GeoPath;
+import org.apache.lucene.spatial3d.geom.GeoPoint;
+import org.apache.lucene.spatial3d.geom.GeoPolygonFactory;
+import org.apache.lucene.spatial3d.geom.GeoShape;
+import org.apache.lucene.spatial3d.geom.PlanetModel;
 import org.junit.Rule;
 import org.junit.Test;
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeSphereModelRectRelationTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeSphereModelRectRelationTest.java b/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeSphereModelRectRelationTest.java
index 2d95823..3bce480 100644
--- a/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeSphereModelRectRelationTest.java
+++ b/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeSphereModelRectRelationTest.java
@@ -20,14 +20,14 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.locationtech.spatial4j.shape.Rectangle;
-import org.apache.lucene.geo3d.GeoArea;
-import org.apache.lucene.geo3d.GeoBBox;
-import org.apache.lucene.geo3d.GeoBBoxFactory;
-import org.apache.lucene.geo3d.GeoStandardCircle;
-import org.apache.lucene.geo3d.GeoPoint;
-import org.apache.lucene.geo3d.GeoPolygonFactory;
-import org.apache.lucene.geo3d.GeoShape;
-import org.apache.lucene.geo3d.PlanetModel;
+import org.apache.lucene.spatial3d.geom.GeoArea;
+import org.apache.lucene.spatial3d.geom.GeoBBox;
+import org.apache.lucene.spatial3d.geom.GeoBBoxFactory;
+import org.apache.lucene.spatial3d.geom.GeoStandardCircle;
+import org.apache.lucene.spatial3d.geom.GeoPoint;
+import org.apache.lucene.spatial3d.geom.GeoPolygonFactory;
+import org.apache.lucene.spatial3d.geom.GeoShape;
+import org.apache.lucene.spatial3d.geom.PlanetModel;
 import org.junit.Test;
 
 public class Geo3dShapeSphereModelRectRelationTest extends Geo3dShapeRectRelationTestCase {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeWGS84ModelRectRelationTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeWGS84ModelRectRelationTest.java b/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeWGS84ModelRectRelationTest.java
index 3b026c3..b59d7df 100644
--- a/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeWGS84ModelRectRelationTest.java
+++ b/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeWGS84ModelRectRelationTest.java
@@ -16,14 +16,14 @@
  */
 package org.apache.lucene.spatial.spatial4j;
 
-import org.apache.lucene.geo3d.GeoArea;
-import org.apache.lucene.geo3d.GeoBBox;
-import org.apache.lucene.geo3d.GeoBBoxFactory;
-import org.apache.lucene.geo3d.GeoCircle;
-import org.apache.lucene.geo3d.GeoStandardCircle;
-import org.apache.lucene.geo3d.GeoPath;
-import org.apache.lucene.geo3d.GeoPoint;
-import org.apache.lucene.geo3d.PlanetModel;
+import org.apache.lucene.spatial3d.geom.GeoArea;
+import org.apache.lucene.spatial3d.geom.GeoBBox;
+import org.apache.lucene.spatial3d.geom.GeoBBoxFactory;
+import org.apache.lucene.spatial3d.geom.GeoCircle;
+import org.apache.lucene.spatial3d.geom.GeoStandardCircle;
+import org.apache.lucene.spatial3d.geom.GeoPath;
+import org.apache.lucene.spatial3d.geom.GeoPoint;
+import org.apache.lucene.spatial3d.geom.PlanetModel;
 import org.junit.Test;
 
 public class Geo3dShapeWGS84ModelRectRelationTest extends Geo3dShapeRectRelationTestCase {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoPointTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoPointTest.java b/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoPointTest.java
deleted file mode 100644
index 4446474..0000000
--- a/lucene/spatial-extras/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoPointTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.spatial.spatial4j.geo3d;
-
-import org.apache.lucene.geo3d.GeoPoint;
-import org.apache.lucene.geo3d.PlanetModel;
-import org.apache.lucene.util.LuceneTestCase;
-import org.junit.Test;
-
-import org.locationtech.spatial4j.distance.DistanceUtils;
-
-import static com.carrotsearch.randomizedtesting.RandomizedTest.randomFloat;
-
-/**
- * Test basic GeoPoint functionality.
- */
-public class GeoPointTest extends LuceneTestCase {
-
-  @Test
-  public void testConversion() {
-    testPointRoundTrip(PlanetModel.SPHERE, 90 * DistanceUtils.DEGREES_TO_RADIANS, 0, 1e-6);
-    testPointRoundTrip(PlanetModel.SPHERE, -90 * DistanceUtils.DEGREES_TO_RADIANS, 0, 1e-6);
-    testPointRoundTrip(PlanetModel.WGS84, 90 * DistanceUtils.DEGREES_TO_RADIANS, 0, 1e-6);
-    testPointRoundTrip(PlanetModel.WGS84, -90 * DistanceUtils.DEGREES_TO_RADIANS, 0, 1e-6);
-
-    final int times = atLeast(100);
-    for (int i = 0; i < times; i++) {
-      final double pLat = (randomFloat() * 180.0 - 90.0) * DistanceUtils.DEGREES_TO_RADIANS;
-      final double pLon = (randomFloat() * 360.0 - 180.0) * DistanceUtils.DEGREES_TO_RADIANS;
-      testPointRoundTrip(PlanetModel.SPHERE, pLat, pLon, 1e-6);//1e-6 since there's a square root in there (Karl says)
-      testPointRoundTrip(PlanetModel.WGS84, pLat, pLon, 1e-6);
-    }
-  }
-
-  protected void testPointRoundTrip(PlanetModel planetModel, double pLat, double pLon, double epsilon) {
-    final GeoPoint p1 = new GeoPoint(planetModel, pLat, pLon);
-    // In order to force the reverse conversion, we have to construct a geopoint from just x,y,z
-    final GeoPoint p2 = new GeoPoint(p1.x, p1.y, p1.z);
-    // Now, construct the final point based on getLatitude() and getLongitude()
-    final GeoPoint p3 = new GeoPoint(planetModel, p2.getLatitude(), p2.getLongitude());
-    double dist = p1.arcDistance(p3);
-    assertEquals(0, dist, epsilon);
-  }
-
-  @Test
-  public void testSurfaceDistance() {
-    final int times = atLeast(100);
-    for (int i = 0; i < times; i++) {
-      final double p1Lat = (randomFloat() * 180.0 - 90.0) * DistanceUtils.DEGREES_TO_RADIANS;
-      final double p1Lon = (randomFloat() * 360.0 - 180.0) * DistanceUtils.DEGREES_TO_RADIANS;
-      final double p2Lat = (randomFloat() * 180.0 - 90.0) * DistanceUtils.DEGREES_TO_RADIANS;
-      final double p2Lon = (randomFloat() * 360.0 - 180.0) * DistanceUtils.DEGREES_TO_RADIANS;
-      final GeoPoint p1 = new GeoPoint(PlanetModel.SPHERE, p1Lat, p1Lon);
-      final GeoPoint p2 = new GeoPoint(PlanetModel.SPHERE, p2Lat, p2Lon);
-      final double arcDistance = p1.arcDistance(p2);
-      // Compute ellipsoid distance; it should agree for a sphere
-      final double surfaceDistance = PlanetModel.SPHERE.surfaceDistance(p1,p2);
-      assertEquals(arcDistance, surfaceDistance, 1e-6);
-    }
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void testBadLatLon() {
-    new GeoPoint(PlanetModel.SPHERE, 50.0, 32.2);
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/ArcDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/ArcDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/ArcDistance.java
deleted file mode 100644
index c49fd1f..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/ArcDistance.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Arc distance computation style.
- *
- * @lucene.experimental
- */
-public class ArcDistance implements DistanceStyle {
-  
-  /** An instance of the ArcDistance DistanceStyle. */
-  public final static ArcDistance INSTANCE = new ArcDistance();
-  
-  /** Constructor.
-   */
-  public ArcDistance() {
-  }
-  
-  @Override
-  public double computeDistance(final GeoPoint point1, final GeoPoint point2) {
-    return point1.arcDistance(point2);
-  }
-  
-  @Override
-  public double computeDistance(final GeoPoint point1, final double x2, final double y2, final double z2) {
-    return point1.arcDistance(x2,y2,z2);
-  }
-
-  @Override
-  public double computeDistance(final PlanetModel planetModel, final Plane plane, final GeoPoint point, final Membership... bounds) {
-    return plane.arcDistance(planetModel, point, bounds);
-  }
-  
-  @Override
-  public double computeDistance(final PlanetModel planetModel, final Plane plane, final double x, final double y, final double z, final Membership... bounds) {
-    return plane.arcDistance(planetModel, x,y,z, bounds);
-  }
-
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/BasePlanetObject.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/BasePlanetObject.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/BasePlanetObject.java
deleted file mode 100644
index c64b974..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/BasePlanetObject.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * All Geo3D shapes can derive from this base class, which furnishes
- * some common code
- *
- * @lucene.internal
- */
-public abstract class BasePlanetObject {
-
-  /** This is the planet model embedded in all objects derived from this
-   * class. */
-  protected final PlanetModel planetModel;
-  
-  /** Constructor creating class instance given a planet model.
-   * @param planetModel is the planet model.
-   */
-  public BasePlanetObject(final PlanetModel planetModel) {
-    this.planetModel = planetModel;
-  }
-
-  /** Returns the {@link PlanetModel} provided when this shape was created. */
-  public PlanetModel getPlanetModel() {
-    return planetModel;
-  }
-  
-  @Override
-  public int hashCode() {
-    return planetModel.hashCode();
-  }
-  
-  @Override
-  public boolean equals(final Object o) {
-    if (!(o instanceof BasePlanetObject))
-      return false;
-    return planetModel.equals(((BasePlanetObject)o).planetModel);
-  }
-}
-
-
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/BaseXYZSolid.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/BaseXYZSolid.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/BaseXYZSolid.java
deleted file mode 100644
index 52bd5da..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/BaseXYZSolid.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Base class of a family of 3D rectangles, bounded on six sides by X,Y,Z limits
- *
- * @lucene.internal
- */
-public abstract class BaseXYZSolid extends BasePlanetObject implements XYZSolid {
-
-  /** Unit vector in x */
-  protected static final Vector xUnitVector = new Vector(1.0, 0.0, 0.0);
-  /** Unit vector in y */
-  protected static final Vector yUnitVector = new Vector(0.0, 1.0, 0.0);
-  /** Unit vector in z */
-  protected static final Vector zUnitVector = new Vector(0.0, 0.0, 1.0);
-  
-  /** Vertical plane normal to x unit vector passing through origin */
-  protected static final Plane xVerticalPlane = new Plane(0.0, 1.0, 0.0, 0.0);
-  /** Vertical plane normal to y unit vector passing through origin */
-  protected static final Plane yVerticalPlane = new Plane(1.0, 0.0, 0.0, 0.0);
-
-  /** Empty point vector */
-  protected static final GeoPoint[] EMPTY_POINTS = new GeoPoint[0];
-  
-  /**
-   * Base solid constructor.
-   *@param planetModel is the planet model.
-   */
-  public BaseXYZSolid(final PlanetModel planetModel) {
-    super(planetModel);
-  }
-  
-  /** Construct a single array from a number of individual arrays.
-   * @param pointArrays is the array of point arrays.
-   * @return the single unified array.
-   */
-  protected static GeoPoint[] glueTogether(final GeoPoint[]... pointArrays) {
-    int count = 0;
-    for (final GeoPoint[] pointArray : pointArrays) {
-      count += pointArray.length;
-    }
-    final GeoPoint[] rval = new GeoPoint[count];
-    count = 0;
-    for (final GeoPoint[] pointArray : pointArrays) {
-      for (final GeoPoint point : pointArray) {
-        rval[count++] = point;
-      }
-    }
-    return rval;
-  }
-  
-  @Override
-  public boolean isWithin(final Vector point) {
-    return isWithin(point.x, point.y, point.z);
-  }
-  
-  @Override
-  public abstract boolean isWithin(final double x, final double y, final double z);
-  
-  // Signals for relationship of edge points to shape
-  
-  /** All edgepoints inside shape */
-  protected final static int ALL_INSIDE = 0;
-  /** Some edgepoints inside shape */
-  protected final static int SOME_INSIDE = 1;
-  /** No edgepoints inside shape */
-  protected final static int NONE_INSIDE = 2;
-  /** No edgepoints at all (means a shape that is the whole world) */
-  protected final static int NO_EDGEPOINTS = 3;
-
-  /** Determine the relationship between this area and the provided
-   * shape's edgepoints.
-   *@param path is the shape.
-   *@return the relationship.
-   */
-  protected int isShapeInsideArea(final GeoShape path) {
-    final GeoPoint[] pathPoints = path.getEdgePoints();
-    if (pathPoints.length == 0)
-      return NO_EDGEPOINTS;
-    boolean foundOutside = false;
-    boolean foundInside = false;
-    for (final GeoPoint p : pathPoints) {
-      if (isWithin(p)) {
-        foundInside = true;
-      } else {
-        foundOutside = true;
-      }
-      if (foundInside && foundOutside) {
-        return SOME_INSIDE;
-      }
-    }
-    if (!foundInside && !foundOutside)
-      return NONE_INSIDE;
-    if (foundInside && !foundOutside)
-      return ALL_INSIDE;
-    if (foundOutside && !foundInside)
-      return NONE_INSIDE;
-    return SOME_INSIDE;
-  }
-
-  /** Determine the relationship between a shape and this area's
-   * edgepoints.
-   *@param path is the shape.
-   *@return the relationship.
-   */
-  protected int isAreaInsideShape(final GeoShape path) {
-    final GeoPoint[] edgePoints = getEdgePoints();
-    if (edgePoints.length == 0) {
-      return NO_EDGEPOINTS;
-    }
-    boolean foundOutside = false;
-    boolean foundInside = false;
-    for (final GeoPoint p : edgePoints) {
-      if (path.isWithin(p)) {
-        foundInside = true;
-      } else {
-        foundOutside = true;
-      }
-      if (foundInside && foundOutside) {
-        return SOME_INSIDE;
-      }
-    }
-    if (!foundInside && !foundOutside)
-      return NONE_INSIDE;
-    if (foundInside && !foundOutside)
-      return ALL_INSIDE;
-    if (foundOutside && !foundInside)
-      return NONE_INSIDE;
-    return SOME_INSIDE;
-  }
-
-  /** Get the edge points for this shape.
-   *@return the edge points.
-   */
-  protected abstract GeoPoint[] getEdgePoints();
-  
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof BaseXYZSolid))
-      return false;
-    BaseXYZSolid other = (BaseXYZSolid) o;
-    return super.equals(other);
-  }
-
-  @Override
-  public int hashCode() {
-    return super.hashCode();
-  }
-
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Bounds.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Bounds.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Bounds.java
deleted file mode 100755
index 6717220..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Bounds.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * 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:
- * (1) No longitude bound possible
- * (2) No upper latitude bound possible
- * (3) No lower latitude bound possible
- * When any of these have been applied, further application of
- * points cannot override that decision.
- *
- * @lucene.experimental
- */
-public interface Bounds {
-
-  /** 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.
-   *@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 single point.
-   *@param point is the point.
-   *@return the updated Bounds object.
-   */
-  public Bounds addPoint(final GeoPoint point);
-
-  /** Add an X value.
-   *@param point is the point to take the x value from.
-   *@return the updated object.
-   */
-  public Bounds addXValue(final GeoPoint point);
-
-  /** Add a Y value.
-   *@param point is the point to take the y value from.
-   *@return the updated object.
-   */
-  public Bounds addYValue(final GeoPoint point);
-
-  /** Add a Z value.
-   *@param point is the point to take the z value from.
-   *@return the updated object.
-   */
-  public Bounds addZValue(final GeoPoint point);
-  
-  /** Signal that the shape exceeds Math.PI in longitude.
-   *@return the updated Bounds object.
-   */
-  public Bounds isWide();
-  
-  /** Signal that there is no longitude bound.
-   *@return the updated Bounds object.
-   */
-  public Bounds noLongitudeBound();
-
-  /** Signal that there is no top latitude bound.
-   *@return the updated Bounds object.
-   */
-  public Bounds noTopLatitudeBound();
-
-  /** Signal that there is no bottom latitude bound.
-   *@return the updated Bounds object.
-   */
-  public Bounds noBottomLatitudeBound();
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/DistanceStyle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/DistanceStyle.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/DistanceStyle.java
deleted file mode 100644
index 28056cb..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/DistanceStyle.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Distance computation styles, supporting various ways of computing
- * distance to shapes.
- *
- * @lucene.experimental
- */
-public interface DistanceStyle {
-
-  // convenient access to built-in styles:
-
-  /** Arc distance calculator */
-  public static final ArcDistance ARC = ArcDistance.INSTANCE;
-  /** Linear distance calculator */
-  public static final LinearDistance LINEAR = LinearDistance.INSTANCE;
-  /** Linear distance squared calculator */
-  public static final LinearSquaredDistance LINEAR_SQUARED = LinearSquaredDistance.INSTANCE;
-  /** Normal distance calculator */
-  public static final NormalDistance NORMAL = NormalDistance.INSTANCE;
-  /** Normal distance squared calculator */
-  public static final NormalSquaredDistance NORMAL_SQUARED = NormalSquaredDistance.INSTANCE;
-
-  /** Compute the distance from a point to another point.
-   * @param point1 Starting point
-   * @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);
-  }
-  
-  /** Compute the distance from a point to another point.
-   * @param point1 Starting point
-   * @param x2 Final point x
-   * @param y2 Final point y
-   * @param z2 Final point z
-   * @return the distance
-   */
-  public double computeDistance(final GeoPoint point1, final double x2, final double y2, final double z2);
-
-  /** Compute the distance from a plane to a point.
-   * @param planetModel The planet model
-   * @param plane The plane
-   * @param point The point
-   * @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);
-  }
-  
-  /** Compute the distance from a plane to a point.
-   * @param planetModel The planet model
-   * @param plane The plane
-   * @param x The point x
-   * @param y The point y
-   * @param z The point z
-   * @param bounds are the plane bounds
-   * @return the distance
-   */
-  public double computeDistance(final PlanetModel planetModel, final Plane plane, final double x, final double y, final double z, final Membership... bounds);
-
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Geo3DPoint.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Geo3DPoint.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Geo3DPoint.java
deleted file mode 100644
index cde87f3..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Geo3DPoint.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-import org.apache.lucene.document.Field;
-import org.apache.lucene.document.FieldType;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.NumericUtils;
-import org.apache.lucene.util.RamUsageEstimator;
-
-/**
- * Add this to a document to index lat/lon or x/y/z point, indexed as a 3D point.
- * Multiple values are allowed: just add multiple Geo3DPoint to the document with the
- * same field name.
- * <p>
- * This field defines static factory methods for creating a shape query:
- * <ul>
- *   <li>{@link #newShapeQuery newShapeQuery()} for matching all points inside a specified shape
- * </ul>
- *
- *  @lucene.experimental */
-public final class Geo3DPoint extends Field {
-
-  /** Indexing {@link FieldType}. */
-  public static final FieldType TYPE = new FieldType();
-  static {
-    TYPE.setDimensions(3, Integer.BYTES);
-    TYPE.freeze();
-  }
-
-  /** 
-   * Creates a new Geo3DPoint field with the specified lat, lon (in radians).
-   *
-   * @throws IllegalArgumentException if the field name is null or lat or lon are out of bounds
-   */
-  public Geo3DPoint(String name, double lat, double lon) {
-    super(name, TYPE);
-    // Translate lat/lon to x,y,z:
-    final GeoPoint point = new GeoPoint(PlanetModel.WGS84, lat, lon);
-    fillFieldsData(point.x, point.y, point.z);
-  }
-
-  /** 
-   * Creates a new Geo3DPoint field with the specified x,y,z.
-   *
-   * @throws IllegalArgumentException if the field name is null or lat or lon are out of bounds
-   */
-  public Geo3DPoint(String name, double x, double y, double z) {
-    super(name, TYPE);
-    fillFieldsData(x, y, z);
-  }
-
-  private void fillFieldsData(double x, double y, double z) {
-    byte[] bytes = new byte[12];
-    encodeDimension(x, bytes, 0);
-    encodeDimension(y, bytes, Integer.BYTES);
-    encodeDimension(z, bytes, 2*Integer.BYTES);
-    fieldsData = new BytesRef(bytes);
-  }
-
-  // public helper methods (e.g. for queries)
-  
-  /** Encode single dimension */
-  public static void encodeDimension(double value, byte bytes[], int offset) {
-    NumericUtils.intToSortableBytes(Geo3DUtil.encodeValue(PlanetModel.WGS84.getMaximumMagnitude(), value), bytes, offset);
-  }
-  
-  /** Decode single dimension */
-  public static double decodeDimension(byte value[], int offset) {
-    return Geo3DUtil.decodeValueCenter(PlanetModel.WGS84.getMaximumMagnitude(), NumericUtils.sortableBytesToInt(value, offset));
-  }
-
-  /** Returns a query matching all points inside the provided shape.
-   * 
-   * @param field field name. must not be {@code null}.
-   * @param shape Which {@link GeoShape} to match
-   */
-  public static Query newShapeQuery(String field, GeoShape shape) {
-    return new PointInGeo3DShapeQuery(field, shape);
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder result = new StringBuilder();
-    result.append(getClass().getSimpleName());
-    result.append(" <");
-    result.append(name);
-    result.append(':');
-
-    BytesRef bytes = (BytesRef) fieldsData;
-    result.append(" x=" + decodeDimension(bytes.bytes, bytes.offset));
-    result.append(" y=" + decodeDimension(bytes.bytes, bytes.offset + Integer.BYTES));
-    result.append(" z=" + decodeDimension(bytes.bytes, bytes.offset + 2*Integer.BYTES));
-    result.append('>');
-    return result.toString();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Geo3DUtil.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Geo3DUtil.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Geo3DUtil.java
deleted file mode 100644
index 34880a1..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Geo3DUtil.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-class Geo3DUtil {
-
-  /** Clips the incoming value to the allowed min/max range before encoding, instead of throwing an exception. */
-  public static int encodeValueLenient(double planetMax, double x) {
-    if (x > planetMax) {
-      x = planetMax;
-    } else if (x < -planetMax) {
-      x = -planetMax;
-    }
-    return encodeValue(planetMax, x);
-  }
-
-  public static int encodeValue(double planetMax, double x) {
-    if (x > planetMax) {
-      throw new IllegalArgumentException("value=" + x + " is out-of-bounds (greater than planetMax=" + planetMax + ")");
-    }
-    if (x < -planetMax) {
-      throw new IllegalArgumentException("value=" + x + " is out-of-bounds (less than than -planetMax=" + -planetMax + ")");
-    }
-    long y = Math.round (x * (Integer.MAX_VALUE / planetMax));
-    assert y >= Integer.MIN_VALUE;
-    assert y <= Integer.MAX_VALUE;
-
-    return (int) y;
-  }
-
-  /** Center decode */
-  public static double decodeValueCenter(double planetMax, int x) {
-    return x * (planetMax / Integer.MAX_VALUE);
-  }
-
-  /** More negative decode, at bottom of cell */
-  public static double decodeValueMin(double planetMax, int x) {
-    return (((double)x) - 0.5) * (planetMax / Integer.MAX_VALUE);
-  }
-  
-  /** More positive decode, at top of cell  */
-  public static double decodeValueMax(double planetMax, int x) {
-    return (((double)x) + 0.5) * (planetMax / Integer.MAX_VALUE);
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoArea.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoArea.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoArea.java
deleted file mode 100755
index 424e494..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoArea.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * A GeoArea represents a standard 2-D breakdown of a part of sphere.  It can
- * be bounded in latitude, or bounded in both latitude and longitude, or not
- * bounded at all.  The purpose of the interface is to describe bounding shapes used for
- * computation of geo hashes.
- *
- * @lucene.experimental
- */
-public interface GeoArea extends Membership {
-  // Since we don't know what each GeoArea's constraints are,
-  // we put the onus on the GeoArea implementation to do the right thing.
-  // This will, of course, rely heavily on methods provided by
-  // the underlying GeoShape class.
-
-  // Relationship values for "getRelationship()"
-  
-  /** The referenced shape CONTAINS this area */
-  public static final int CONTAINS = 0;
-  /** The referenced shape IS WITHIN this area */
-  public static final int WITHIN = 1;
-  /** The referenced shape OVERLAPS this area */
-  public static final int OVERLAPS = 2;
-  /** The referenced shape has no relation to this area */
-  public static final int DISJOINT = 3;
-
-  /**
-   * 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.
-   *
-   * It is permissible to return OVERLAPS instead of WITHIN if the shape
-   * intersects with the area at even a single point.  So, a circle inscribed in
-   * a rectangle could return either OVERLAPS or WITHIN, depending on
-   * implementation.  It is not permissible to return CONTAINS or DISJOINT
-   * in this circumstance, however.
-   *
-   * Similarly, it is permissible to return OVERLAPS instead of CONTAINS
-   * under conditions where the shape consists of multiple independent overlapping
-   * subshapes, and the area overlaps one of the subshapes.  It is not permissible
-   * to return WITHIN or DISJOINT in this circumstance, however.
-   *
-   * @param shape is the shape to consider.
-   * @return the relationship, from the perspective of the shape.
-   */
-  public int getRelationship(GeoShape shape);
-}
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoAreaFactory.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoAreaFactory.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoAreaFactory.java
deleted file mode 100755
index 24dd211..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoAreaFactory.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Factory for {@link org.apache.lucene.geo3d.GeoArea}.
- *
- * @lucene.experimental
- */
-public class GeoAreaFactory {
-  private GeoAreaFactory() {
-  }
-
-  /**
-   * Create a GeoArea of the right kind given the specified bounds.
-   * @param planetModel is the planet model
-   * @param topLat    is the top latitude
-   * @param bottomLat is the bottom latitude
-   * @param leftLon   is the left longitude
-   * @param rightLon  is the right longitude
-   * @return a GeoArea corresponding to what was specified.
-   */
-  public static GeoArea makeGeoArea(final PlanetModel planetModel, final double topLat, final double bottomLat, final double leftLon, final double rightLon) {
-    return GeoBBoxFactory.makeGeoBBox(planetModel, topLat, bottomLat, leftLon, rightLon);
-  }
-
-  /**
-   * Create a GeoArea of the right kind given (x,y,z) bounds.
-   * @param planetModel is the planet model
-   * @param minX is the min X boundary
-   * @param maxX is the max X boundary
-   * @param minY is the min Y boundary
-   * @param maxY is the max Y boundary
-   * @param minZ is the min Z boundary
-   * @param maxZ is the max Z boundary
-   */
-  public static GeoArea makeGeoArea(final PlanetModel planetModel, final double minX, final double maxX, final double minY, final double maxY, final double minZ, final double maxZ) {
-    return XYZSolidFactory.makeXYZSolid(planetModel, minX, maxX, minY, maxY, minZ, maxZ);
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBBox.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBBox.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBBox.java
deleted file mode 100755
index 10a2388..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBBox.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * All bounding box shapes have this interface in common.
- * This describes methods that bounding boxes have above and beyond
- * GeoMembershipShape's.
- *
- * @lucene.experimental
- */
-public interface GeoBBox extends GeoMembershipShape, GeoSizeable, GeoArea {
-
-  /**
-   * Expand box by specified angle.
-   *
-   * @param angle is the angle amount to expand the GeoBBox by.
-   * @return a new GeoBBox.
-   */
-  public GeoBBox expand(double angle);
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBBoxFactory.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBBoxFactory.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBBoxFactory.java
deleted file mode 100755
index 9a02ab9..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBBoxFactory.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Factory for {@link org.apache.lucene.geo3d.GeoBBox}.
- *
- * @lucene.experimental
- */
-public class GeoBBoxFactory {
-  private GeoBBoxFactory() {
-  }
-
-  /**
-   * Create a geobbox of the right kind given the specified bounds.
-   *
-   * @param planetModel is the planet model
-   * @param topLat    is the top latitude
-   * @param bottomLat is the bottom latitude
-   * @param leftLon   is the left longitude
-   * @param rightLon  is the right longitude
-   * @return a GeoBBox corresponding to what was specified.
-   */
-  public static GeoBBox makeGeoBBox(final PlanetModel planetModel, double topLat, double bottomLat, double leftLon, double rightLon) {
-    //System.err.println("Making rectangle for topLat="+topLat*180.0/Math.PI+", bottomLat="+bottomLat*180.0/Math.PI+", leftLon="+leftLon*180.0/Math.PI+", rightlon="+rightLon*180.0/Math.PI);
-    if (topLat > Math.PI * 0.5)
-      topLat = Math.PI * 0.5;
-    if (bottomLat < -Math.PI * 0.5)
-      bottomLat = -Math.PI * 0.5;
-    if (leftLon < -Math.PI)
-      leftLon = -Math.PI;
-    if (rightLon > Math.PI)
-      rightLon = Math.PI;
-    if (Math.abs(leftLon + Math.PI) < Vector.MINIMUM_RESOLUTION && Math.abs(rightLon - Math.PI) < Vector.MINIMUM_RESOLUTION) {
-      if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION && Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION)
-        return new GeoWorld(planetModel);
-      if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION) {
-        if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION || Math.abs(topLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION)
-          return new GeoDegeneratePoint(planetModel, topLat, 0.0);
-        return new GeoDegenerateLatitudeZone(planetModel, topLat);
-      }
-      if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION)
-        return new GeoNorthLatitudeZone(planetModel, bottomLat);
-      else if (Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION)
-        return new GeoSouthLatitudeZone(planetModel, topLat);
-      return new GeoLatitudeZone(planetModel, topLat, bottomLat);
-    }
-    //System.err.println(" not latitude zone");
-    double extent = rightLon - leftLon;
-    if (extent < 0.0)
-      extent += Math.PI * 2.0;
-    if (topLat == Math.PI * 0.5 && bottomLat == -Math.PI * 0.5) {
-      if (Math.abs(leftLon - rightLon) < Vector.MINIMUM_RESOLUTION)
-        return new GeoDegenerateLongitudeSlice(planetModel, leftLon);
-
-      if (extent >= Math.PI)
-        return new GeoWideLongitudeSlice(planetModel, leftLon, rightLon);
-
-      return new GeoLongitudeSlice(planetModel, leftLon, rightLon);
-    }
-    //System.err.println(" not longitude slice");
-    if (Math.abs(leftLon - rightLon) < Vector.MINIMUM_RESOLUTION) {
-      if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION)
-        return new GeoDegeneratePoint(planetModel, topLat, leftLon);
-      return new GeoDegenerateVerticalLine(planetModel, topLat, bottomLat, leftLon);
-    }
-    //System.err.println(" not vertical line");
-    if (extent >= Math.PI) {
-      if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION) {
-        //System.err.println(" wide degenerate line");
-        return new GeoWideDegenerateHorizontalLine(planetModel, topLat, leftLon, rightLon);
-      }
-      if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION) {
-        return new GeoWideNorthRectangle(planetModel, bottomLat, leftLon, rightLon);
-      } else if (Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION) {
-        return new GeoWideSouthRectangle(planetModel, topLat, leftLon, rightLon);
-      }
-      //System.err.println(" wide rect");
-      return new GeoWideRectangle(planetModel, topLat, bottomLat, leftLon, rightLon);
-    }
-    if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION) {
-      if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION || Math.abs(topLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION) {
-        return new GeoDegeneratePoint(planetModel, topLat, 0.0);
-      }
-      //System.err.println(" horizontal line");
-      return new GeoDegenerateHorizontalLine(planetModel, topLat, leftLon, rightLon);
-    }
-    if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION) {
-      return new GeoNorthRectangle(planetModel, bottomLat, leftLon, rightLon);
-    } else if (Math.abs(bottomLat + Math.PI * 0.5) <  Vector.MINIMUM_RESOLUTION) {
-      return new GeoSouthRectangle(planetModel, topLat, leftLon, rightLon);
-    }
-    //System.err.println(" rectangle");
-    return new GeoRectangle(planetModel, topLat, bottomLat, leftLon, rightLon);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseBBox.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseBBox.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseBBox.java
deleted file mode 100644
index f40a0a1..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseBBox.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * All bounding box shapes can derive from this base class, which furnishes
- * some common code
- *
- * @lucene.internal
- */
-public abstract class GeoBaseBBox extends GeoBaseMembershipShape implements GeoBBox {
-
-  /** Construct, given planet model.
-   *@param planetModel is the planet model.
-   */
-  public GeoBaseBBox(final PlanetModel planetModel) {
-    super(planetModel);
-  }
-
-  // Signals for relationship of edge points to shape
-  
-  /** All edgepoints inside shape */
-  protected final static int ALL_INSIDE = 0;
-  /** Some edgepoints inside shape */
-  protected final static int SOME_INSIDE = 1;
-  /** No edgepoints inside shape */
-  protected final static int NONE_INSIDE = 2;
-
-  /** Determine the relationship between this BBox and the provided
-   * shape's edgepoints.
-   *@param path is the shape.
-   *@return the relationship.
-   */
-  protected int isShapeInsideBBox(final GeoShape path) {
-    final GeoPoint[] pathPoints = path.getEdgePoints();
-    boolean foundOutside = false;
-    boolean foundInside = false;
-    for (GeoPoint p : pathPoints) {
-      if (isWithin(p)) {
-        foundInside = true;
-      } else {
-        foundOutside = true;
-      }
-      if (foundInside && foundOutside) {
-        return SOME_INSIDE;
-      }
-    }
-    if (!foundInside && !foundOutside)
-      return NONE_INSIDE;
-    if (foundInside && !foundOutside)
-      return ALL_INSIDE;
-    if (foundOutside && !foundInside)
-      return NONE_INSIDE;
-    return SOME_INSIDE;
-  }
-
-}
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseCircle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseCircle.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseCircle.java
deleted file mode 100644
index 8c306d7..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseCircle.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * GeoCircles have all the characteristics of GeoBaseDistanceShapes, plus GeoSizeable.
- *
- * @lucene.experimental
- */
-public abstract class GeoBaseCircle extends GeoBaseDistanceShape implements GeoCircle {
-
-  /** Constructor.
-   *@param planetModel is the planet model to use.
-   */
-  public GeoBaseCircle(final PlanetModel planetModel) {
-    super(planetModel);
-  }
-
-}
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseDistanceShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseDistanceShape.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseDistanceShape.java
deleted file mode 100644
index 1c8306a..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseDistanceShape.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Distance shapes have capabilities of both geohashing and distance
- * computation (which also includes point membership determination).
- *
- * @lucene.experimental
- */
-public abstract class GeoBaseDistanceShape extends GeoBaseMembershipShape implements GeoDistanceShape {
-
-  /** Constructor.
-   *@param planetModel is the planet model to use.
-   */
-  public GeoBaseDistanceShape(final PlanetModel planetModel) {
-    super(planetModel);
-  }
-
-  @Override
-  public boolean isWithin(Vector point) {
-    return isWithin(point.x, point.y, point.z);
-  }
-
-  @Override
-  public double computeDistance(final DistanceStyle distanceStyle, final GeoPoint point) {
-    return computeDistance(distanceStyle, point.x, point.y, point.z);
-  }
-
-  @Override
-  public double computeDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
-    if (!isWithin(x,y,z)) {
-      return Double.MAX_VALUE;
-    }
-    return distance(distanceStyle, x, y, z);
-  }
-
-  /** Called by a {@code computeDistance} method if X/Y/Z is not within this shape. */
-  protected abstract double distance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
-
-}
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseMembershipShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseMembershipShape.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseMembershipShape.java
deleted file mode 100644
index a6bba8f..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseMembershipShape.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Membership shapes have capabilities of both geohashing and membership
- * determination.  This is a useful baseclass for them.
- *
- * @lucene.experimental
- */
-public abstract class GeoBaseMembershipShape extends GeoBaseShape implements GeoMembershipShape {
-
-  /** Constructor.
-   *@param planetModel is the planet model to use.
-   */
-  public GeoBaseMembershipShape(final PlanetModel planetModel) {
-    super(planetModel);
-  }
-
-  @Override
-  public boolean isWithin(Vector point) {
-    return isWithin(point.x, point.y, point.z);
-  }
-
-  @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;
-    }
-    return outsideDistance(distanceStyle, x,y,z);
-  }
-
-  /** Called by a {@code computeOutsideDistance} method if X/Y/Z is not within this shape. */
-  protected abstract double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z);
-
-}
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBasePolygon.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBasePolygon.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBasePolygon.java
deleted file mode 100644
index 50ad0dc..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBasePolygon.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * GeoBasePolygon objects are the base class of most GeoPolygon objects.
- *
- * @lucene.experimental
- */
-public abstract class GeoBasePolygon extends GeoBaseMembershipShape implements GeoPolygon {
-
-  /** Constructor.
-   *@param planetModel is the planet model to use.
-   */
-  public GeoBasePolygon(final PlanetModel planetModel) {
-    super(planetModel);
-  }
-
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseShape.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseShape.java
deleted file mode 100644
index 146cfe8..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoBaseShape.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Base extended shape object.
- *
- * @lucene.internal
- */
-public abstract class GeoBaseShape extends BasePlanetObject implements GeoShape {
-
-  /** Constructor.
-   *@param planetModel is the planet model to use.
-   */
-  public GeoBaseShape(final PlanetModel planetModel) {
-    super(planetModel);
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    if (isWithin(planetModel.NORTH_POLE)) {
-      bounds.noTopLatitudeBound().noLongitudeBound()
-        .addPoint(planetModel.NORTH_POLE);
-    }
-    if (isWithin(planetModel.SOUTH_POLE)) {
-      bounds.noBottomLatitudeBound().noLongitudeBound()
-        .addPoint(planetModel.SOUTH_POLE);
-    }
-    if (isWithin(planetModel.MIN_X_POLE)) {
-      bounds.addPoint(planetModel.MIN_X_POLE);
-    }
-    if (isWithin(planetModel.MAX_X_POLE)) {
-      bounds.addPoint(planetModel.MAX_X_POLE);
-    }
-    if (isWithin(planetModel.MIN_Y_POLE)) {
-      bounds.addPoint(planetModel.MIN_Y_POLE);
-    }
-    if (isWithin(planetModel.MAX_Y_POLE)) {
-      bounds.addPoint(planetModel.MAX_Y_POLE);
-    }
-  }
-
-}
-
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCircle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCircle.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCircle.java
deleted file mode 100755
index 154cdc4..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCircle.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Interface describing circular area with a center and radius.
- *
- * @lucene.experimental
- */
-public interface GeoCircle extends GeoDistanceShape, GeoSizeable {
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCircleFactory.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCircleFactory.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCircleFactory.java
deleted file mode 100644
index 2bb8ffc..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCircleFactory.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * Class which constructs a GeoCircle representing an arbitrary circle.
- *
- * @lucene.experimental
- */
-public class GeoCircleFactory {
-  private GeoCircleFactory() {
-  }
-
-  /**
-   * Create a GeoCircle of the right kind given the specified bounds.
-   * @param planetModel is the planet model.
-   * @param latitude is the center latitude.
-   * @param longitude is the center longitude.
-   * @param radius is the radius angle.
-   * @return a GeoCircle corresponding to what was specified.
-   */
-  public static GeoCircle makeGeoCircle(final PlanetModel planetModel, final double latitude, final double longitude, final double radius) {
-    if (radius < Vector.MINIMUM_RESOLUTION) {
-      return new GeoDegeneratePoint(planetModel, latitude, longitude);
-    }
-    return new GeoStandardCircle(planetModel, latitude, longitude, radius);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCompositeMembershipShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCompositeMembershipShape.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCompositeMembershipShape.java
deleted file mode 100755
index 25bdda0..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCompositeMembershipShape.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * GeoComposite is a set of GeoMembershipShape's, treated as a unit.
- *
- * @lucene.experimental
- */
-public class GeoCompositeMembershipShape implements GeoMembershipShape {
-  /** The list of shapes. */
-  protected final List<GeoMembershipShape> shapes = new ArrayList<GeoMembershipShape>();
-
-  /** Constructor.
-   */
-  public GeoCompositeMembershipShape() {
-  }
-
-  /**
-   * Add a shape to the composite.
-   *@param shape is the shape to add.
-   */
-  public void addShape(final GeoMembershipShape shape) {
-    shapes.add(shape);
-  }
-
-  @Override
-  public boolean isWithin(final Vector point) {
-    return isWithin(point.x, point.y, point.z);
-  }
-
-  @Override
-  public boolean isWithin(final double x, final double y, final double z) {
-    for (GeoMembershipShape shape : shapes) {
-      if (shape.isWithin(x, y, z))
-        return true;
-    }
-    return false;
-  }
-
-  @Override
-  public GeoPoint[] getEdgePoints() {
-    return shapes.get(0).getEdgePoints();
-  }
-
-  @Override
-  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
-    for (GeoMembershipShape shape : shapes) {
-      if (shape.intersects(p, notablePoints, bounds))
-        return true;
-    }
-    return false;
-  }
-
-  @Override
-  public void getBounds(Bounds bounds) {
-    for (GeoMembershipShape shape : shapes) {
-      shape.getBounds(bounds);
-    }
-  }
-
-  @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;
-
-    return super.equals(o) && shapes.equals(other.shapes);
-  }
-
-  @Override
-  public int hashCode() {
-    return super.hashCode() * 31 + shapes.hashCode();//TODO cache
-  }
-
-  @Override
-  public String toString() {
-    return "GeoCompositeMembershipShape: {" + shapes + '}';
-  }
-}
-  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCompositePolygon.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCompositePolygon.java b/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCompositePolygon.java
deleted file mode 100644
index b537590..0000000
--- a/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoCompositePolygon.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-/**
- * GeoCompositePolygon is a specific implementation of GeoMembershipShape, which implements GeoPolygon explicitly.
- *
- * @lucene.experimental
- */
-public class GeoCompositePolygon extends GeoCompositeMembershipShape implements GeoPolygon {
-  /** Constructor.
-   */
-  public GeoCompositePolygon() {
-  }
-
-}
-  


[09/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/geo3d/PlaneTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/PlaneTest.java b/lucene/spatial3d/src/test/org/apache/lucene/geo3d/PlaneTest.java
deleted file mode 100644
index 2ac3856..0000000
--- a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/PlaneTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Test basic plane functionality.
- */
-public class PlaneTest {
-
-
-  @Test
-  public void testIdenticalPlanes() {
-    final GeoPoint p = new GeoPoint(PlanetModel.SPHERE, 0.123, -0.456);
-    final Plane plane1 = new Plane(p, 0.0);
-    final Plane plane2 = new Plane(p, 0.0);
-    assertTrue(plane1.isNumericallyIdentical(plane2));
-    final Plane plane3 = new Plane(p, 0.1);
-    assertFalse(plane1.isNumericallyIdentical(plane3));
-    final Vector v1 = new Vector(0.1, -0.732, 0.9);
-    final double constant = 0.432;
-    final Vector v2 = new Vector(v1.x * constant, v1.y * constant, v1.z * constant);
-    final Plane p1 = new Plane(v1, 0.2);
-    final Plane p2 = new Plane(v2, 0.2 * constant);
-    assertTrue(p1.isNumericallyIdentical(p2));
-  }
-
-  @Test
-  public void testInterpolation() {
-    // [X=0.35168818443386646, Y=-0.19637966197066342, Z=0.9152870857244183],
-    // [X=0.5003343189532654, Y=0.522128543226148, Z=0.6906861469771293],
-
-    final GeoPoint start = new GeoPoint(0.35168818443386646, -0.19637966197066342, 0.9152870857244183);
-    final GeoPoint end = new GeoPoint(0.5003343189532654, 0.522128543226148, 0.6906861469771293);
-
-    // [A=-0.6135342247741855, B=0.21504338363863665, C=0.28188192383666794, D=0.0, side=-1.0] internal? false;
-    final Plane p = new Plane(-0.6135342247741855, 0.21504338363863665, 0.28188192383666794, 0.0);
-
-    final GeoPoint[] points = p.interpolate(start, end, new double[]{0.25, 0.50, 0.75});
-
-    for (GeoPoint point : points) {
-      assertTrue(p.evaluateIsZero(point));
-    }
-  }
-}
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/geo3d/TestGeo3DPoint.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/TestGeo3DPoint.java b/lucene/spatial3d/src/test/org/apache/lucene/geo3d/TestGeo3DPoint.java
deleted file mode 100644
index 17a4075..0000000
--- a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/TestGeo3DPoint.java
+++ /dev/null
@@ -1,801 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.lucene.codecs.Codec;
-import org.apache.lucene.codecs.FilterCodec;
-import org.apache.lucene.codecs.PointsFormat;
-import org.apache.lucene.codecs.PointsReader;
-import org.apache.lucene.codecs.PointsWriter;
-import org.apache.lucene.codecs.lucene60.Lucene60PointsReader;
-import org.apache.lucene.codecs.lucene60.Lucene60PointsWriter;
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
-import org.apache.lucene.document.NumericDocValuesField;
-import org.apache.lucene.index.DirectoryReader;
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.IndexWriter;
-import org.apache.lucene.index.IndexWriterConfig;
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.index.MultiDocValues;
-import org.apache.lucene.index.NumericDocValues;
-import org.apache.lucene.index.SegmentReadState;
-import org.apache.lucene.index.SegmentWriteState;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.SimpleCollector;
-import org.apache.lucene.store.Directory;
-import org.apache.lucene.store.MockDirectoryWrapper;
-import org.apache.lucene.util.FixedBitSet;
-import org.apache.lucene.util.IOUtils;
-import org.apache.lucene.util.LuceneTestCase;
-import org.apache.lucene.util.TestUtil;
-import org.junit.BeforeClass;
-
-import com.carrotsearch.randomizedtesting.generators.RandomInts;
-
-public class TestGeo3DPoint extends LuceneTestCase {
-
-  private static boolean smallBBox;
-  
-  @BeforeClass
-  public static void beforeClass() {
-    smallBBox = random().nextBoolean();
-    if (VERBOSE) {
-      System.err.println("TEST: smallBBox=" + smallBBox);
-    }
-  }
-
-  private static Codec getCodec() {
-    if (Codec.getDefault().getName().equals("Lucene60")) {
-      int maxPointsInLeafNode = TestUtil.nextInt(random(), 16, 2048);
-      double maxMBSortInHeap = 3.0 + (3*random().nextDouble());
-      if (VERBOSE) {
-        System.out.println("TEST: using Lucene60PointsFormat with maxPointsInLeafNode=" + maxPointsInLeafNode + " and maxMBSortInHeap=" + maxMBSortInHeap);
-      }
-
-      return new FilterCodec("Lucene60", Codec.getDefault()) {
-        @Override
-        public PointsFormat pointsFormat() {
-          return new PointsFormat() {
-            @Override
-            public PointsWriter fieldsWriter(SegmentWriteState writeState) throws IOException {
-              return new Lucene60PointsWriter(writeState, maxPointsInLeafNode, maxMBSortInHeap);
-            }
-
-            @Override
-            public PointsReader fieldsReader(SegmentReadState readState) throws IOException {
-              return new Lucene60PointsReader(readState);
-            }
-          };
-        }
-      };
-    } else {
-      return Codec.getDefault();
-    }
-  }
-
-  public void testBasic() throws Exception {
-    Directory dir = getDirectory();
-    IndexWriterConfig iwc = newIndexWriterConfig();
-    iwc.setCodec(getCodec());
-    IndexWriter w = new IndexWriter(dir, iwc);
-    Document doc = new Document();
-    doc.add(new Geo3DPoint("field", toRadians(50.7345267), toRadians(-97.5303555)));
-    w.addDocument(doc);
-    IndexReader r = DirectoryReader.open(w);
-    // We can't wrap with "exotic" readers because the query must see the BKD3DDVFormat:
-    IndexSearcher s = newSearcher(r, false);
-    assertEquals(1, s.search(Geo3DPoint.newShapeQuery("field",
-                                                      GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84, toRadians(50), toRadians(-97), Math.PI/180.)), 1).totalHits);
-    w.close();
-    r.close();
-    dir.close();
-  }
-
-  private static double toRadians(double degrees) {
-    return Math.PI*(degrees/360.0);
-  }
-
-  private static PlanetModel getPlanetModel() {
-    if (random().nextBoolean()) {
-      // Use one of the earth models:
-      if (random().nextBoolean()) {
-        return PlanetModel.WGS84;
-      } else {
-        return PlanetModel.SPHERE;
-      }
-    } else {
-      // Make a randomly squashed planet:
-      double oblateness = random().nextDouble() * 0.5 - 0.25;
-      return new PlanetModel(1.0 + oblateness, 1.0 - oblateness);
-    }
-  }
-
-  private static class Cell {
-    static int nextCellID;
-
-    final Cell parent;
-    final int cellID;
-    final int xMinEnc, xMaxEnc;
-    final int yMinEnc, yMaxEnc;
-    final int zMinEnc, zMaxEnc;
-    final int splitCount;
-
-    public Cell(Cell parent,
-                int xMinEnc, int xMaxEnc,
-                int yMinEnc, int yMaxEnc,
-                int zMinEnc, int zMaxEnc,
-                int splitCount) {
-      this.parent = parent;
-      this.xMinEnc = xMinEnc;
-      this.xMaxEnc = xMaxEnc;
-      this.yMinEnc = yMinEnc;
-      this.yMaxEnc = yMaxEnc;
-      this.zMinEnc = zMinEnc;
-      this.zMaxEnc = zMaxEnc;
-      this.cellID = nextCellID++;
-      this.splitCount = splitCount;
-    }
-
-    /** Returns true if the quantized point lies within this cell, inclusive on all bounds. */
-    public boolean contains(double planetMax, GeoPoint point) {
-      int docX = Geo3DUtil.encodeValue(planetMax, point.x);
-      int docY = Geo3DUtil.encodeValue(planetMax, point.y);
-      int docZ = Geo3DUtil.encodeValue(planetMax, point.z);
-
-      return docX >= xMinEnc && docX <= xMaxEnc &&
-        docY >= yMinEnc && docY <= yMaxEnc && 
-        docZ >= zMinEnc && docZ <= zMaxEnc;
-    }
-
-    @Override
-    public String toString() {
-      return "cell=" + cellID + (parent == null ? "" : " parentCellID=" + parent.cellID) + " x: " + xMinEnc + " TO " + xMaxEnc + ", y: " + yMinEnc + " TO " + yMaxEnc + ", z: " + zMinEnc + " TO " + zMaxEnc + ", splits: " + splitCount;
-    }
-  }
-
-  private static GeoPoint quantize(double planetMax, GeoPoint point) {
-    return new GeoPoint(Geo3DUtil.decodeValueCenter(planetMax, Geo3DUtil.encodeValue(planetMax, point.x)),
-                        Geo3DUtil.decodeValueCenter(planetMax, Geo3DUtil.encodeValue(planetMax, point.y)),
-                        Geo3DUtil.decodeValueCenter(planetMax, Geo3DUtil.encodeValue(planetMax, point.z)));
-  }
-
-  /** Tests consistency of GeoArea.getRelationship vs GeoShape.isWithin */
-  public void testGeo3DRelations() throws Exception {
-
-    PlanetModel planetModel = getPlanetModel();
-
-    int numDocs = atLeast(1000);
-    if (VERBOSE) {
-      System.out.println("TEST: " + numDocs + " docs");
-    }
-
-    GeoPoint[] docs = new GeoPoint[numDocs];
-    for(int docID=0;docID<numDocs;docID++) {
-      docs[docID] = new GeoPoint(planetModel, toRadians(randomLat()), toRadians(randomLon()));
-      if (VERBOSE) {
-        System.out.println("  doc=" + docID + ": " + docs[docID]);
-      }
-    }
-
-    double planetMax = planetModel.getMaximumMagnitude();
-
-    int iters = atLeast(10);
-
-    int recurseDepth = RandomInts.randomIntBetween(random(), 5, 15);
-
-    iters = atLeast(50);
-    
-    for(int iter=0;iter<iters;iter++) {
-      GeoShape shape = randomShape(planetModel);
-
-      StringWriter sw = new StringWriter();
-      PrintWriter log = new PrintWriter(sw, true);
-
-      if (VERBOSE) {
-        log.println("TEST: iter=" + iter + " shape=" + shape);
-      }
-
-      XYZBounds bounds = new XYZBounds();
-      shape.getBounds(bounds);
-
-      // Start with the root cell that fully contains the shape:
-      Cell root = new Cell(null,
-                           Geo3DUtil.encodeValueLenient(planetMax, bounds.getMinimumX()),
-                           Geo3DUtil.encodeValueLenient(planetMax, bounds.getMaximumX()),
-                           Geo3DUtil.encodeValueLenient(planetMax, bounds.getMinimumY()),
-                           Geo3DUtil.encodeValueLenient(planetMax, bounds.getMaximumY()),
-                           Geo3DUtil.encodeValueLenient(planetMax, bounds.getMinimumZ()),
-                           Geo3DUtil.encodeValueLenient(planetMax, bounds.getMaximumZ()),
-                           0);
-
-      if (VERBOSE) {
-        log.println("  root cell: " + root);
-      }
-
-      List<Cell> queue = new ArrayList<>();
-      queue.add(root);
-      Set<Integer> hits = new HashSet<>();
-
-      while (queue.size() > 0) {
-        Cell cell = queue.get(queue.size()-1);
-        queue.remove(queue.size()-1);
-        if (VERBOSE) {
-          log.println("  cycle: " + cell + " queue.size()=" + queue.size());
-        }
-
-        if (random().nextInt(10) == 7 || cell.splitCount > recurseDepth) {
-          if (VERBOSE) {
-            log.println("    leaf");
-          }
-          // Leaf cell: brute force check all docs that fall within this cell:
-          for(int docID=0;docID<numDocs;docID++) {
-            GeoPoint point = docs[docID];
-            if (cell.contains(planetMax, point)) {
-              if (shape.isWithin(quantize(planetMax, point))) {
-                if (VERBOSE) {
-                  log.println("    check doc=" + docID + ": match!");
-                }
-                hits.add(docID);
-              } else {
-                if (VERBOSE) {
-                  log.println("    check doc=" + docID + ": no match");
-                }
-              }
-            }
-          }
-        } else {
-          
-          GeoArea xyzSolid = GeoAreaFactory.makeGeoArea(planetModel,
-                                                        Geo3DUtil.decodeValueMin(planetMax, cell.xMinEnc), Geo3DUtil.decodeValueMax(planetMax, cell.xMaxEnc),
-                                                        Geo3DUtil.decodeValueMin(planetMax, cell.yMinEnc), Geo3DUtil.decodeValueMax(planetMax, cell.yMaxEnc),
-                                                        Geo3DUtil.decodeValueMin(planetMax, cell.zMinEnc), Geo3DUtil.decodeValueMax(planetMax, cell.zMaxEnc));
-
-          if (VERBOSE) {
-            log.println("    minx="+Geo3DUtil.decodeValueMin(planetMax, cell.xMinEnc)+" maxx="+Geo3DUtil.decodeValueMax(planetMax, cell.xMaxEnc)+
-              " miny="+Geo3DUtil.decodeValueMin(planetMax, cell.yMinEnc)+" maxy="+Geo3DUtil.decodeValueMax(planetMax, cell.yMaxEnc)+
-              " minz="+Geo3DUtil.decodeValueMin(planetMax, cell.zMinEnc)+" maxz="+Geo3DUtil.decodeValueMax(planetMax, cell.zMaxEnc));
-          }
-
-          switch (xyzSolid.getRelationship(shape)) {          
-          case GeoArea.CONTAINS:
-            // Shape fully contains the cell: blindly add all docs in this cell:
-            if (VERBOSE) {
-              log.println("    GeoArea.CONTAINS: now addAll");
-            }
-            for(int docID=0;docID<numDocs;docID++) {
-              if (cell.contains(planetMax, docs[docID])) {
-                if (VERBOSE) {
-                  log.println("    addAll doc=" + docID);
-                }
-                hits.add(docID);
-              }
-            }
-            continue;
-          case GeoArea.OVERLAPS:
-            if (VERBOSE) {
-              log.println("    GeoArea.OVERLAPS: keep splitting");
-            }
-            // They do overlap but neither contains the other:
-            //log.println("    crosses1");
-            break;
-          case GeoArea.WITHIN:
-            if (VERBOSE) {
-              log.println("    GeoArea.WITHIN: keep splitting");
-            }
-            // Cell fully contains the shape:
-            //log.println("    crosses2");
-            break;
-          case GeoArea.DISJOINT:
-            // They do not overlap at all: don't recurse on this cell
-            //log.println("    outside");
-            if (VERBOSE) {
-              log.println("    GeoArea.DISJOINT: drop this cell");
-              for(int docID=0;docID<numDocs;docID++) {
-                if (cell.contains(planetMax, docs[docID])) {
-                  if (VERBOSE) {
-                    log.println("    skip doc=" + docID);
-                  }
-                }
-              }
-            }
-            continue;
-          default:
-            assert false;
-          }
-
-          // Randomly split:
-          switch(random().nextInt(3)) {
-
-          case 0:
-            // Split on X:
-            {
-              int splitValue = RandomInts.randomIntBetween(random(), cell.xMinEnc, cell.xMaxEnc);
-              if (VERBOSE) {
-                log.println("    now split on x=" + splitValue);
-              }
-              Cell cell1 = new Cell(cell,
-                                 cell.xMinEnc, splitValue,
-                                 cell.yMinEnc, cell.yMaxEnc,
-                                 cell.zMinEnc, cell.zMaxEnc,
-                                 cell.splitCount+1);
-              Cell cell2 = new Cell(cell,
-                                 splitValue, cell.xMaxEnc,
-                                 cell.yMinEnc, cell.yMaxEnc,
-                                 cell.zMinEnc, cell.zMaxEnc,
-                                 cell.splitCount+1);
-              if (VERBOSE) {
-                log.println("    split cell1: " + cell1);
-                log.println("    split cell2: " + cell2);
-              }
-              queue.add(cell1);
-              queue.add(cell2);
-            }
-            break;
-
-          case 1:
-            // Split on Y:
-            {
-              int splitValue = RandomInts.randomIntBetween(random(), cell.yMinEnc, cell.yMaxEnc);
-              if (VERBOSE) {
-                log.println("    now split on y=" + splitValue);
-              }
-              Cell cell1 = new Cell(cell,
-                                 cell.xMinEnc, cell.xMaxEnc,
-                                 cell.yMinEnc, splitValue,
-                                 cell.zMinEnc, cell.zMaxEnc,
-                                 cell.splitCount+1);
-              Cell cell2 = new Cell(cell,
-                                 cell.xMinEnc, cell.xMaxEnc,
-                                 splitValue, cell.yMaxEnc,
-                                 cell.zMinEnc, cell.zMaxEnc,
-                                 cell.splitCount+1);
-              if (VERBOSE) {
-                log.println("    split cell1: " + cell1);
-                log.println("    split cell2: " + cell2);
-              }
-              queue.add(cell1);
-              queue.add(cell2);
-            }
-            break;
-
-          case 2:
-            // Split on Z:
-            {
-              int splitValue = RandomInts.randomIntBetween(random(), cell.zMinEnc, cell.zMaxEnc);
-              if (VERBOSE) {
-                log.println("    now split on z=" + splitValue);
-              }
-              Cell cell1 = new Cell(cell,
-                                 cell.xMinEnc, cell.xMaxEnc,
-                                 cell.yMinEnc, cell.yMaxEnc,
-                                 cell.zMinEnc, splitValue,
-                                 cell.splitCount+1);
-              Cell cell2 = new Cell(cell,
-                                 cell.xMinEnc, cell.xMaxEnc,
-                                 cell.yMinEnc, cell.yMaxEnc,
-                                 splitValue, cell.zMaxEnc,
-                                 cell.splitCount+1);
-              if (VERBOSE) {
-                log.println("    split cell1: " + cell1);
-                log.println("    split cell2: " + cell2);
-              }
-              queue.add(cell1);
-              queue.add(cell2);
-            }
-            break;
-          }
-        }
-      }
-
-      if (VERBOSE) {
-        log.println("  " + hits.size() + " hits");
-      }
-
-      // Done matching, now verify:
-      boolean fail = false;
-      for(int docID=0;docID<numDocs;docID++) {
-        GeoPoint point = docs[docID];
-        GeoPoint quantized = quantize(planetMax, point);
-        boolean expected = shape.isWithin(quantized);
-
-        if (expected != shape.isWithin(point)) {
-          // Quantization changed the result; skip testing this doc:
-          continue;
-        }
-
-        boolean actual = hits.contains(docID);
-        if (actual != expected) {
-          if (actual) {
-            log.println("doc=" + docID + " matched but should not");
-          } else {
-            log.println("doc=" + docID + " did not match but should");
-          }
-          log.println("  point=" + docs[docID]);
-          log.println("  quantized=" + quantize(planetMax, docs[docID]));
-          fail = true;
-        }
-      }
-
-      if (fail) {
-        System.out.print(sw.toString());
-        fail("invalid hits for shape=" + shape);
-      }
-    }
-  }
-
-  public void testRandomTiny() throws Exception {
-    // Make sure single-leaf-node case is OK:
-    doTestRandom(10);
-  }
-
-  public void testRandomMedium() throws Exception {
-    doTestRandom(10000);
-  }
-
-  @Nightly
-  public void testRandomBig() throws Exception {
-    doTestRandom(200000);
-  }
-
-  private void doTestRandom(int count) throws Exception {
-    int numPoints = atLeast(count);
-
-    if (VERBOSE) {
-      System.err.println("TEST: numPoints=" + numPoints);
-    }
-
-    double[] lats = new double[numPoints];
-    double[] lons = new double[numPoints];
-
-    boolean haveRealDoc = false;
-
-    for (int docID=0;docID<numPoints;docID++) {
-      int x = random().nextInt(20);
-      if (x == 17) {
-        // Some docs don't have a point:
-        lats[docID] = Double.NaN;
-        if (VERBOSE) {
-          System.err.println("  doc=" + docID + " is missing");
-        }
-        continue;
-      }
-
-      if (docID > 0 && x < 3 && haveRealDoc) {
-        int oldDocID;
-        while (true) {
-          oldDocID = random().nextInt(docID);
-          if (Double.isNaN(lats[oldDocID]) == false) {
-            break;
-          }
-        }
-            
-        if (x == 0) {
-          // Identical lat to old point
-          lats[docID] = lats[oldDocID];
-          lons[docID] = toRadians(randomLon());
-          if (VERBOSE) {
-            System.err.println("  doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID] + " (same lat as doc=" + oldDocID + ")");
-          }
-        } else if (x == 1) {
-          // Identical lon to old point
-          lats[docID] = toRadians(randomLat());
-          lons[docID] = lons[oldDocID];
-          if (VERBOSE) {
-            System.err.println("  doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID] + " (same lon as doc=" + oldDocID + ")");
-          }
-        } else {
-          assert x == 2;
-          // Fully identical point:
-          lats[docID] = lats[oldDocID];
-          lons[docID] = lons[oldDocID];
-          if (VERBOSE) {
-            System.err.println("  doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID] + " (same lat/lon as doc=" + oldDocID + ")");
-          }
-        }
-      } else {
-        lats[docID] = toRadians(randomLat());
-        lons[docID] = toRadians(randomLon());
-        haveRealDoc = true;
-        if (VERBOSE) {
-          System.err.println("  doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID]);
-        }
-      }
-    }
-
-    verify(lats, lons);
-  }
-
-  private static double randomLat() {
-    if (smallBBox) {
-      return 2.0 * (random().nextDouble()-0.5);
-    } else {
-      return -90 + 180.0 * random().nextDouble();
-    }
-  }
-
-  private static double randomLon() {
-    if (smallBBox) {
-      return 2.0 * (random().nextDouble()-0.5);
-    } else {
-      return -180 + 360.0 * random().nextDouble();
-    }
-  }
-
-  // Poached from Geo3dRptTest.randomShape:
-  private static GeoShape randomShape(PlanetModel planetModel) {
-    while (true) {
-      final int shapeType = random().nextInt(4);
-      switch (shapeType) {
-      case 0: {
-        // Polygons
-        final int vertexCount = random().nextInt(3) + 3;
-        final List<GeoPoint> geoPoints = new ArrayList<>();
-        while (geoPoints.size() < vertexCount) {
-          final GeoPoint gPt = new GeoPoint(planetModel, toRadians(randomLat()), toRadians(randomLon()));
-          geoPoints.add(gPt);
-        }
-        final int convexPointIndex = random().nextInt(vertexCount);       //If we get this wrong, hopefully we get IllegalArgumentException
-        try {
-          return GeoPolygonFactory.makeGeoPolygon(planetModel, geoPoints, convexPointIndex);
-        } catch (IllegalArgumentException e) {
-          // This is what happens when we create a shape that is invalid.  Although it is conceivable that there are cases where
-          // the exception is thrown incorrectly, we aren't going to be able to do that in this random test.
-          continue;
-        }
-      }
-
-      case 1: {
-        // Circles
-
-        double lat = toRadians(randomLat());
-        double lon = toRadians(randomLon());
-
-        double angle;
-        if (smallBBox) {
-          angle = random().nextDouble() * Math.PI/360.0;
-        } else {
-          angle = random().nextDouble() * Math.PI/2.0;
-        }
-
-        try {
-          return GeoCircleFactory.makeGeoCircle(planetModel, lat, lon, angle);
-        } catch (IllegalArgumentException iae) {
-          // angle is too small; try again:
-          continue;
-        }
-      }
-
-      case 2: {
-        // Rectangles
-        double lat0 = toRadians(randomLat());
-        double lat1 = toRadians(randomLat());
-        if (lat1 < lat0) {
-          double x = lat0;
-          lat0 = lat1;
-          lat1 = x;
-        }
-        double lon0 = toRadians(randomLon());
-        double lon1 = toRadians(randomLon());
-        if (lon1 < lon0) {
-          double x = lon0;
-          lon0 = lon1;
-          lon1 = x;
-        }
-
-        return GeoBBoxFactory.makeGeoBBox(planetModel, lat1, lat0, lon0, lon1);
-      }
-
-      case 3: {
-        // Paths
-        final int pointCount = random().nextInt(5) + 1;
-        final double width = toRadians(random().nextInt(89)+1);
-        try {
-          final GeoPath path = new GeoPath(planetModel, width);
-          for (int i = 0; i < pointCount; i++) {
-            path.addPoint(toRadians(randomLat()), toRadians(randomLon()));
-          }
-          path.done();
-          return path;
-        } catch (IllegalArgumentException e) {
-          // This is what happens when we create a shape that is invalid.  Although it is conceivable that there are cases where
-          // the exception is thrown incorrectly, we aren't going to be able to do that in this random test.
-          continue;
-        }
-      }
-
-      default:
-        throw new IllegalStateException("Unexpected shape type");
-      }
-    }
-  }
-
-  private static void verify(double[] lats, double[] lons) throws Exception {
-    IndexWriterConfig iwc = newIndexWriterConfig();
-
-    // Else we can get O(N^2) merging:
-    int mbd = iwc.getMaxBufferedDocs();
-    if (mbd != -1 && mbd < lats.length/100) {
-      iwc.setMaxBufferedDocs(lats.length/100);
-    }
-    iwc.setCodec(getCodec());
-    Directory dir;
-    if (lats.length > 100000) {
-      dir = newFSDirectory(createTempDir("TestBKDTree"));
-    } else {
-      dir = getDirectory();
-    }
-    Set<Integer> deleted = new HashSet<>();
-    // RandomIndexWriter is too slow here:
-    IndexWriter w = new IndexWriter(dir, iwc);
-    for(int id=0;id<lats.length;id++) {
-      Document doc = new Document();
-      doc.add(newStringField("id", ""+id, Field.Store.NO));
-      doc.add(new NumericDocValuesField("id", id));
-      if (Double.isNaN(lats[id]) == false) {
-        doc.add(new Geo3DPoint("point", lats[id], lons[id]));
-      }
-      w.addDocument(doc);
-      if (id > 0 && random().nextInt(100) == 42) {
-        int idToDelete = random().nextInt(id);
-        w.deleteDocuments(new Term("id", ""+idToDelete));
-        deleted.add(idToDelete);
-        if (VERBOSE) {
-          System.err.println("  delete id=" + idToDelete);
-        }
-      }
-    }
-    if (random().nextBoolean()) {
-      w.forceMerge(1);
-    }
-    final IndexReader r = DirectoryReader.open(w);
-    w.close();
-
-    // We can't wrap with "exotic" readers because the geo3d query must see the Geo3DDVFormat:
-    IndexSearcher s = newSearcher(r, false);
-
-    int numThreads = TestUtil.nextInt(random(), 2, 5);
-
-    List<Thread> threads = new ArrayList<>();
-    final int iters = atLeast(100);
-
-    final CountDownLatch startingGun = new CountDownLatch(1);
-    final AtomicBoolean failed = new AtomicBoolean();
-
-    for(int i=0;i<numThreads;i++) {
-      Thread thread = new Thread() {
-          @Override
-          public void run() {
-            try {
-              _run();
-            } catch (Exception e) {
-              failed.set(true);
-              throw new RuntimeException(e);
-            }
-          }
-
-          private void _run() throws Exception {
-            startingGun.await();
-
-            NumericDocValues docIDToID = MultiDocValues.getNumericValues(r, "id");
-
-            for (int iter=0;iter<iters && failed.get() == false;iter++) {
-
-              GeoShape shape = randomShape(PlanetModel.WGS84);
-
-              if (VERBOSE) {
-                System.err.println("\n" + Thread.currentThread() + ": TEST: iter=" + iter + " shape="+shape);
-              }
-              
-              Query query = Geo3DPoint.newShapeQuery("point", shape);
-
-              if (VERBOSE) {
-                System.err.println("  using query: " + query);
-              }
-
-              final FixedBitSet hits = new FixedBitSet(r.maxDoc());
-
-              s.search(query, new SimpleCollector() {
-
-                  private int docBase;
-
-                  @Override
-                  public boolean needsScores() {
-                    return false;
-                  }
-
-                  @Override
-                  protected void doSetNextReader(LeafReaderContext context) throws IOException {
-                    docBase = context.docBase;
-                  }
-
-                  @Override
-                  public void collect(int doc) {
-                    hits.set(docBase+doc);
-                  }
-                });
-
-              if (VERBOSE) {
-                System.err.println("  hitCount: " + hits.cardinality());
-              }
-      
-              for(int docID=0;docID<r.maxDoc();docID++) {
-                int id = (int) docIDToID.get(docID);
-                if (Double.isNaN(lats[id]) == false) {
-
-                  // Accurate point:
-                  GeoPoint point1 = new GeoPoint(PlanetModel.WGS84, lats[id], lons[id]);
-
-                  // Quantized point (32 bits per dim):
-                  GeoPoint point2 = quantize(PlanetModel.WGS84.getMaximumMagnitude(), point1);
-
-                  if (shape.isWithin(point1) != shape.isWithin(point2)) {
-                    if (VERBOSE) {
-                      System.out.println("  skip checking docID=" + docID + " quantization changed the expected result from " + shape.isWithin(point1) + " to " + shape.isWithin(point2));
-                    }
-                    continue;
-                  }
-
-                  boolean expected = ((deleted.contains(id) == false) && shape.isWithin(point2));
-                  if (hits.get(docID) != expected) {
-                    fail(Thread.currentThread().getName() + ": iter=" + iter + " id=" + id + " docID=" + docID + " lat=" + lats[id] + " lon=" + lons[id] + " expected " + expected + " but got: " + hits.get(docID) + " deleted?=" + deleted.contains(id) + "\n  point1=" + point1 + ", iswithin="+shape.isWithin(point1)+"\n  point2=" + point2 + ", iswithin="+shape.isWithin(point2) + "\n  query=" + query);
-                  }
-                } else {
-                  assertFalse(hits.get(docID));
-                }
-
-              }
-            }
-          }
-        };
-      thread.setName("T" + i);
-      thread.start();
-      threads.add(thread);
-    }
-    startingGun.countDown();
-    for(Thread thread : threads) {
-      thread.join();
-    }
-    IOUtils.close(r, dir);
-  }
-
-  public void testToString() {
-    Geo3DPoint point = new Geo3DPoint("point", toRadians(44.244272), toRadians(7.769736));
-    assertEquals("Geo3DPoint <point: x=0.9248467864160119 y=0.06280434265368656 z=0.37682349005486243>", point.toString());
-  }
-
-  public void testShapeQueryToString() {
-    assertEquals("PointInGeo3DShapeQuery: field=point: Shape: GeoStandardCircle: {planetmodel=PlanetModel.WGS84, center=[lat=0.3861041107739683, lon=0.06780373760536706], radius=0.1(5.729577951308232)}",
-                 Geo3DPoint.newShapeQuery("point", GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84, toRadians(44.244272), toRadians(7.769736), 0.1)).toString());
-  }
-
-  private static Directory getDirectory() {     
-    return newDirectory();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/geo3d/XYZSolidTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/XYZSolidTest.java b/lucene/spatial3d/src/test/org/apache/lucene/geo3d/XYZSolidTest.java
deleted file mode 100644
index 876a525..0000000
--- a/lucene/spatial3d/src/test/org/apache/lucene/geo3d/XYZSolidTest.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * 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.
- */
-package org.apache.lucene.geo3d;
-
-import org.apache.lucene.util.LuceneTestCase;
-import org.junit.Test;
-
-public class XYZSolidTest extends LuceneTestCase {
-
-  @Test
-  public void testNonDegenerateRelationships() {
-    XYZSolid s;
-    GeoShape shape;
-    // Something bigger than the world
-    s = new StandardXYZSolid(PlanetModel.SPHERE, -2.0, 2.0, -2.0, 2.0, -2.0, 2.0);
-    // Any shape, except whole world, should be within.
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.WITHIN, s.getRelationship(shape));
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    // An XYZSolid represents a surface shape, which when larger than the world is in fact
-    // the entire world, so it should overlap the world.
-    assertEquals(GeoArea.OVERLAPS, s.getRelationship(shape));
-
-    // Something overlapping the world on only one side
-    s = new StandardXYZSolid(PlanetModel.SPHERE, -2.0, 0.0, -2.0, 2.0, -2.0, 2.0);
-    // Some things should be disjoint...
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.DISJOINT, s.getRelationship(shape));
-    // And, some things should be within... 
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI, 0.1);
-    assertEquals(GeoArea.WITHIN, s.getRelationship(shape));
-    // And, some things should overlap.
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI * 0.5, 0.1);
-    assertEquals(GeoArea.OVERLAPS, s.getRelationship(shape));
-
-    // Partial world should be contained by GeoWorld object...
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    assertEquals(GeoArea.CONTAINS, s.getRelationship(shape));
-    
-    // Something inside the world
-    s = new StandardXYZSolid(PlanetModel.SPHERE, -0.1, 0.1, -0.1, 0.1, -0.1, 0.1);
-    // All shapes should be disjoint
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.DISJOINT, s.getRelationship(shape));
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    assertEquals(GeoArea.DISJOINT, s.getRelationship(shape));
-    
-  }
-
-  @Test
-  public void testDegenerateRelationships() {
-    GeoArea solid;
-    GeoShape shape;
-    
-    // Basic test of the factory method - non-degenerate
-    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, -2.0, 2.0, -2.0, 2.0, -2.0, 2.0);
-    // Any shape, except whole world, should be within.
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.WITHIN, solid.getRelationship(shape));
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    // An XYZSolid represents a surface shape, which when larger than the world is in fact
-    // the entire world, so it should overlap the world.
-    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
-
-    // Build a degenerate point, not on sphere
-    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
-    // disjoint with everything?
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-
-    // Build a degenerate point that IS on the sphere
-    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0);
-    // inside everything that it touches?
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-
-    // Build a shape degenerate in (x,y), which has no points on sphere
-    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, 0.0, 0.0, -0.1, 0.1);
-    // disjoint with everything?
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-
-    // Build a shape degenerate in (x,y) which has one point on sphere
-    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, 0.0, 0.0, -0.1, 1.1);
-    // inside everything that it touches?
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, Math.PI * 0.5, 0.0, 0.1);
-    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-
-    // Build a shape degenerate in (x,y) which has two points on sphere
-    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, 0.0, 0.0, -1.1, 1.1);
-    // inside everything that it touches?
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, Math.PI * 0.5, 0.0, 0.1);
-    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0, 0.1);
-    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
-    
-    // Build a shape degenerate in (x,z), which has no points on sphere
-    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -0.1, 0.1, 0.0, 0.0);
-    // disjoint with everything?
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-
-    // Build a shape degenerate in (x,z) which has one point on sphere
-    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -0.1, 1.1, 0.0, 0.0);
-    // inside everything that it touches?
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI * 0.5, 0.1);
-    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, -Math.PI * 0.5, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-
-    // Build a shape degenerate in (x,y) which has two points on sphere
-    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -1.1, 1.1, 0.0, 0.0);
-    // inside everything that it touches?
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI * 0.5, 0.1);
-    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, -Math.PI * 0.5, 0.1);
-    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
-
-    // MHL for y-z check
-    
-    // Build a shape that is degenerate in x, which has zero points intersecting sphere
-    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -0.1, 0.1, -0.1, 0.1);
-    // disjoint with everything?
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-
-    // Build a shape that is degenerate in x, which has zero points intersecting sphere, second variation
-    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -0.1, 0.1, 1.1, 1.2);
-    // disjoint with everything?
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-
-    // Build a shape that is disjoint in X but intersects sphere in a complete circle
-    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -1.1, 1.1, -1.1, 1.1);
-    // inside everything that it touches?
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI * 0.5, 0.1);
-    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, -Math.PI * 0.5, 0.1);
-    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, Math.PI * 0.5, 0.0, 0.1);
-    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0, 0.1);
-    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
-
-    // Build a shape that is disjoint in X but intersects sphere in a half circle in Y
-    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, 0.0, 1.1, -1.1, 1.1);
-    // inside everything that it touches?
-    shape = new GeoWorld(PlanetModel.SPHERE);
-    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI * 0.5, 0.1);
-    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, -Math.PI * 0.5, 0.1);
-    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, Math.PI * 0.5, 0.0, 0.1);
-    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
-    shape = new GeoStandardCircle(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0, 0.1);
-    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
-
-    // MHL for degenerate Y
-    // MHL for degenerate Z
-    
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java
new file mode 100644
index 0000000..a4d8ed1
--- /dev/null
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java
@@ -0,0 +1,810 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.lucene.codecs.Codec;
+import org.apache.lucene.codecs.FilterCodec;
+import org.apache.lucene.codecs.PointsFormat;
+import org.apache.lucene.codecs.PointsReader;
+import org.apache.lucene.codecs.PointsWriter;
+import org.apache.lucene.codecs.lucene60.Lucene60PointsReader;
+import org.apache.lucene.codecs.lucene60.Lucene60PointsWriter;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.NumericDocValuesField;
+import org.apache.lucene.spatial3d.geom.GeoArea;
+import org.apache.lucene.spatial3d.geom.GeoAreaFactory;
+import org.apache.lucene.spatial3d.geom.GeoBBoxFactory;
+import org.apache.lucene.spatial3d.geom.GeoCircleFactory;
+import org.apache.lucene.spatial3d.geom.GeoPath;
+import org.apache.lucene.spatial3d.geom.GeoPoint;
+import org.apache.lucene.spatial3d.geom.GeoPolygonFactory;
+import org.apache.lucene.spatial3d.geom.GeoShape;
+import org.apache.lucene.spatial3d.geom.PlanetModel;
+import org.apache.lucene.spatial3d.geom.XYZBounds;
+import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.MultiDocValues;
+import org.apache.lucene.index.NumericDocValues;
+import org.apache.lucene.index.SegmentReadState;
+import org.apache.lucene.index.SegmentWriteState;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.SimpleCollector;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.FixedBitSet;
+import org.apache.lucene.util.IOUtils;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util.TestUtil;
+import org.junit.BeforeClass;
+
+import com.carrotsearch.randomizedtesting.generators.RandomInts;
+
+public class TestGeo3DPoint extends LuceneTestCase {
+
+  private static boolean smallBBox;
+  
+  @BeforeClass
+  public static void beforeClass() {
+    smallBBox = random().nextBoolean();
+    if (VERBOSE) {
+      System.err.println("TEST: smallBBox=" + smallBBox);
+    }
+  }
+
+  private static Codec getCodec() {
+    if (Codec.getDefault().getName().equals("Lucene60")) {
+      int maxPointsInLeafNode = TestUtil.nextInt(random(), 16, 2048);
+      double maxMBSortInHeap = 3.0 + (3*random().nextDouble());
+      if (VERBOSE) {
+        System.out.println("TEST: using Lucene60PointsFormat with maxPointsInLeafNode=" + maxPointsInLeafNode + " and maxMBSortInHeap=" + maxMBSortInHeap);
+      }
+
+      return new FilterCodec("Lucene60", Codec.getDefault()) {
+        @Override
+        public PointsFormat pointsFormat() {
+          return new PointsFormat() {
+            @Override
+            public PointsWriter fieldsWriter(SegmentWriteState writeState) throws IOException {
+              return new Lucene60PointsWriter(writeState, maxPointsInLeafNode, maxMBSortInHeap);
+            }
+
+            @Override
+            public PointsReader fieldsReader(SegmentReadState readState) throws IOException {
+              return new Lucene60PointsReader(readState);
+            }
+          };
+        }
+      };
+    } else {
+      return Codec.getDefault();
+    }
+  }
+
+  public void testBasic() throws Exception {
+    Directory dir = getDirectory();
+    IndexWriterConfig iwc = newIndexWriterConfig();
+    iwc.setCodec(getCodec());
+    IndexWriter w = new IndexWriter(dir, iwc);
+    Document doc = new Document();
+    doc.add(new Geo3DPoint("field", toRadians(50.7345267), toRadians(-97.5303555)));
+    w.addDocument(doc);
+    IndexReader r = DirectoryReader.open(w);
+    // We can't wrap with "exotic" readers because the query must see the BKD3DDVFormat:
+    IndexSearcher s = newSearcher(r, false);
+    assertEquals(1, s.search(Geo3DPoint.newShapeQuery("field",
+                                                      GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84, toRadians(50), toRadians(-97), Math.PI/180.)), 1).totalHits);
+    w.close();
+    r.close();
+    dir.close();
+  }
+
+  private static double toRadians(double degrees) {
+    return Math.PI*(degrees/360.0);
+  }
+
+  private static PlanetModel getPlanetModel() {
+    if (random().nextBoolean()) {
+      // Use one of the earth models:
+      if (random().nextBoolean()) {
+        return PlanetModel.WGS84;
+      } else {
+        return PlanetModel.SPHERE;
+      }
+    } else {
+      // Make a randomly squashed planet:
+      double oblateness = random().nextDouble() * 0.5 - 0.25;
+      return new PlanetModel(1.0 + oblateness, 1.0 - oblateness);
+    }
+  }
+
+  private static class Cell {
+    static int nextCellID;
+
+    final Cell parent;
+    final int cellID;
+    final int xMinEnc, xMaxEnc;
+    final int yMinEnc, yMaxEnc;
+    final int zMinEnc, zMaxEnc;
+    final int splitCount;
+
+    public Cell(Cell parent,
+                int xMinEnc, int xMaxEnc,
+                int yMinEnc, int yMaxEnc,
+                int zMinEnc, int zMaxEnc,
+                int splitCount) {
+      this.parent = parent;
+      this.xMinEnc = xMinEnc;
+      this.xMaxEnc = xMaxEnc;
+      this.yMinEnc = yMinEnc;
+      this.yMaxEnc = yMaxEnc;
+      this.zMinEnc = zMinEnc;
+      this.zMaxEnc = zMaxEnc;
+      this.cellID = nextCellID++;
+      this.splitCount = splitCount;
+    }
+
+    /** Returns true if the quantized point lies within this cell, inclusive on all bounds. */
+    public boolean contains(double planetMax, GeoPoint point) {
+      int docX = Geo3DUtil.encodeValue(planetMax, point.x);
+      int docY = Geo3DUtil.encodeValue(planetMax, point.y);
+      int docZ = Geo3DUtil.encodeValue(planetMax, point.z);
+
+      return docX >= xMinEnc && docX <= xMaxEnc &&
+        docY >= yMinEnc && docY <= yMaxEnc && 
+        docZ >= zMinEnc && docZ <= zMaxEnc;
+    }
+
+    @Override
+    public String toString() {
+      return "cell=" + cellID + (parent == null ? "" : " parentCellID=" + parent.cellID) + " x: " + xMinEnc + " TO " + xMaxEnc + ", y: " + yMinEnc + " TO " + yMaxEnc + ", z: " + zMinEnc + " TO " + zMaxEnc + ", splits: " + splitCount;
+    }
+  }
+
+  private static GeoPoint quantize(double planetMax, GeoPoint point) {
+    return new GeoPoint(Geo3DUtil.decodeValueCenter(planetMax, Geo3DUtil.encodeValue(planetMax, point.x)),
+                        Geo3DUtil.decodeValueCenter(planetMax, Geo3DUtil.encodeValue(planetMax, point.y)),
+                        Geo3DUtil.decodeValueCenter(planetMax, Geo3DUtil.encodeValue(planetMax, point.z)));
+  }
+
+  /** Tests consistency of GeoArea.getRelationship vs GeoShape.isWithin */
+  public void testGeo3DRelations() throws Exception {
+
+    PlanetModel planetModel = getPlanetModel();
+
+    int numDocs = atLeast(1000);
+    if (VERBOSE) {
+      System.out.println("TEST: " + numDocs + " docs");
+    }
+
+    GeoPoint[] docs = new GeoPoint[numDocs];
+    for(int docID=0;docID<numDocs;docID++) {
+      docs[docID] = new GeoPoint(planetModel, toRadians(randomLat()), toRadians(randomLon()));
+      if (VERBOSE) {
+        System.out.println("  doc=" + docID + ": " + docs[docID]);
+      }
+    }
+
+    double planetMax = planetModel.getMaximumMagnitude();
+
+    int iters = atLeast(10);
+
+    int recurseDepth = RandomInts.randomIntBetween(random(), 5, 15);
+
+    iters = atLeast(50);
+    
+    for(int iter=0;iter<iters;iter++) {
+      GeoShape shape = randomShape(planetModel);
+
+      StringWriter sw = new StringWriter();
+      PrintWriter log = new PrintWriter(sw, true);
+
+      if (VERBOSE) {
+        log.println("TEST: iter=" + iter + " shape=" + shape);
+      }
+
+      XYZBounds bounds = new XYZBounds();
+      shape.getBounds(bounds);
+
+      // Start with the root cell that fully contains the shape:
+      Cell root = new Cell(null,
+                           Geo3DUtil.encodeValueLenient(planetMax, bounds.getMinimumX()),
+                           Geo3DUtil.encodeValueLenient(planetMax, bounds.getMaximumX()),
+                           Geo3DUtil.encodeValueLenient(planetMax, bounds.getMinimumY()),
+                           Geo3DUtil.encodeValueLenient(planetMax, bounds.getMaximumY()),
+                           Geo3DUtil.encodeValueLenient(planetMax, bounds.getMinimumZ()),
+                           Geo3DUtil.encodeValueLenient(planetMax, bounds.getMaximumZ()),
+                           0);
+
+      if (VERBOSE) {
+        log.println("  root cell: " + root);
+      }
+
+      List<Cell> queue = new ArrayList<>();
+      queue.add(root);
+      Set<Integer> hits = new HashSet<>();
+
+      while (queue.size() > 0) {
+        Cell cell = queue.get(queue.size()-1);
+        queue.remove(queue.size()-1);
+        if (VERBOSE) {
+          log.println("  cycle: " + cell + " queue.size()=" + queue.size());
+        }
+
+        if (random().nextInt(10) == 7 || cell.splitCount > recurseDepth) {
+          if (VERBOSE) {
+            log.println("    leaf");
+          }
+          // Leaf cell: brute force check all docs that fall within this cell:
+          for(int docID=0;docID<numDocs;docID++) {
+            GeoPoint point = docs[docID];
+            if (cell.contains(planetMax, point)) {
+              if (shape.isWithin(quantize(planetMax, point))) {
+                if (VERBOSE) {
+                  log.println("    check doc=" + docID + ": match!");
+                }
+                hits.add(docID);
+              } else {
+                if (VERBOSE) {
+                  log.println("    check doc=" + docID + ": no match");
+                }
+              }
+            }
+          }
+        } else {
+          
+          GeoArea xyzSolid = GeoAreaFactory.makeGeoArea(planetModel,
+                                                        Geo3DUtil.decodeValueMin(planetMax, cell.xMinEnc), Geo3DUtil.decodeValueMax(planetMax, cell.xMaxEnc),
+                                                        Geo3DUtil.decodeValueMin(planetMax, cell.yMinEnc), Geo3DUtil.decodeValueMax(planetMax, cell.yMaxEnc),
+                                                        Geo3DUtil.decodeValueMin(planetMax, cell.zMinEnc), Geo3DUtil.decodeValueMax(planetMax, cell.zMaxEnc));
+
+          if (VERBOSE) {
+            log.println("    minx="+Geo3DUtil.decodeValueMin(planetMax, cell.xMinEnc)+" maxx="+Geo3DUtil.decodeValueMax(planetMax, cell.xMaxEnc)+
+              " miny="+Geo3DUtil.decodeValueMin(planetMax, cell.yMinEnc)+" maxy="+Geo3DUtil.decodeValueMax(planetMax, cell.yMaxEnc)+
+              " minz="+Geo3DUtil.decodeValueMin(planetMax, cell.zMinEnc)+" maxz="+Geo3DUtil.decodeValueMax(planetMax, cell.zMaxEnc));
+          }
+
+          switch (xyzSolid.getRelationship(shape)) {          
+          case GeoArea.CONTAINS:
+            // Shape fully contains the cell: blindly add all docs in this cell:
+            if (VERBOSE) {
+              log.println("    GeoArea.CONTAINS: now addAll");
+            }
+            for(int docID=0;docID<numDocs;docID++) {
+              if (cell.contains(planetMax, docs[docID])) {
+                if (VERBOSE) {
+                  log.println("    addAll doc=" + docID);
+                }
+                hits.add(docID);
+              }
+            }
+            continue;
+          case GeoArea.OVERLAPS:
+            if (VERBOSE) {
+              log.println("    GeoArea.OVERLAPS: keep splitting");
+            }
+            // They do overlap but neither contains the other:
+            //log.println("    crosses1");
+            break;
+          case GeoArea.WITHIN:
+            if (VERBOSE) {
+              log.println("    GeoArea.WITHIN: keep splitting");
+            }
+            // Cell fully contains the shape:
+            //log.println("    crosses2");
+            break;
+          case GeoArea.DISJOINT:
+            // They do not overlap at all: don't recurse on this cell
+            //log.println("    outside");
+            if (VERBOSE) {
+              log.println("    GeoArea.DISJOINT: drop this cell");
+              for(int docID=0;docID<numDocs;docID++) {
+                if (cell.contains(planetMax, docs[docID])) {
+                  if (VERBOSE) {
+                    log.println("    skip doc=" + docID);
+                  }
+                }
+              }
+            }
+            continue;
+          default:
+            assert false;
+          }
+
+          // Randomly split:
+          switch(random().nextInt(3)) {
+
+          case 0:
+            // Split on X:
+            {
+              int splitValue = RandomInts.randomIntBetween(random(), cell.xMinEnc, cell.xMaxEnc);
+              if (VERBOSE) {
+                log.println("    now split on x=" + splitValue);
+              }
+              Cell cell1 = new Cell(cell,
+                                 cell.xMinEnc, splitValue,
+                                 cell.yMinEnc, cell.yMaxEnc,
+                                 cell.zMinEnc, cell.zMaxEnc,
+                                 cell.splitCount+1);
+              Cell cell2 = new Cell(cell,
+                                 splitValue, cell.xMaxEnc,
+                                 cell.yMinEnc, cell.yMaxEnc,
+                                 cell.zMinEnc, cell.zMaxEnc,
+                                 cell.splitCount+1);
+              if (VERBOSE) {
+                log.println("    split cell1: " + cell1);
+                log.println("    split cell2: " + cell2);
+              }
+              queue.add(cell1);
+              queue.add(cell2);
+            }
+            break;
+
+          case 1:
+            // Split on Y:
+            {
+              int splitValue = RandomInts.randomIntBetween(random(), cell.yMinEnc, cell.yMaxEnc);
+              if (VERBOSE) {
+                log.println("    now split on y=" + splitValue);
+              }
+              Cell cell1 = new Cell(cell,
+                                 cell.xMinEnc, cell.xMaxEnc,
+                                 cell.yMinEnc, splitValue,
+                                 cell.zMinEnc, cell.zMaxEnc,
+                                 cell.splitCount+1);
+              Cell cell2 = new Cell(cell,
+                                 cell.xMinEnc, cell.xMaxEnc,
+                                 splitValue, cell.yMaxEnc,
+                                 cell.zMinEnc, cell.zMaxEnc,
+                                 cell.splitCount+1);
+              if (VERBOSE) {
+                log.println("    split cell1: " + cell1);
+                log.println("    split cell2: " + cell2);
+              }
+              queue.add(cell1);
+              queue.add(cell2);
+            }
+            break;
+
+          case 2:
+            // Split on Z:
+            {
+              int splitValue = RandomInts.randomIntBetween(random(), cell.zMinEnc, cell.zMaxEnc);
+              if (VERBOSE) {
+                log.println("    now split on z=" + splitValue);
+              }
+              Cell cell1 = new Cell(cell,
+                                 cell.xMinEnc, cell.xMaxEnc,
+                                 cell.yMinEnc, cell.yMaxEnc,
+                                 cell.zMinEnc, splitValue,
+                                 cell.splitCount+1);
+              Cell cell2 = new Cell(cell,
+                                 cell.xMinEnc, cell.xMaxEnc,
+                                 cell.yMinEnc, cell.yMaxEnc,
+                                 splitValue, cell.zMaxEnc,
+                                 cell.splitCount+1);
+              if (VERBOSE) {
+                log.println("    split cell1: " + cell1);
+                log.println("    split cell2: " + cell2);
+              }
+              queue.add(cell1);
+              queue.add(cell2);
+            }
+            break;
+          }
+        }
+      }
+
+      if (VERBOSE) {
+        log.println("  " + hits.size() + " hits");
+      }
+
+      // Done matching, now verify:
+      boolean fail = false;
+      for(int docID=0;docID<numDocs;docID++) {
+        GeoPoint point = docs[docID];
+        GeoPoint quantized = quantize(planetMax, point);
+        boolean expected = shape.isWithin(quantized);
+
+        if (expected != shape.isWithin(point)) {
+          // Quantization changed the result; skip testing this doc:
+          continue;
+        }
+
+        boolean actual = hits.contains(docID);
+        if (actual != expected) {
+          if (actual) {
+            log.println("doc=" + docID + " matched but should not");
+          } else {
+            log.println("doc=" + docID + " did not match but should");
+          }
+          log.println("  point=" + docs[docID]);
+          log.println("  quantized=" + quantize(planetMax, docs[docID]));
+          fail = true;
+        }
+      }
+
+      if (fail) {
+        System.out.print(sw.toString());
+        fail("invalid hits for shape=" + shape);
+      }
+    }
+  }
+
+  public void testRandomTiny() throws Exception {
+    // Make sure single-leaf-node case is OK:
+    doTestRandom(10);
+  }
+
+  public void testRandomMedium() throws Exception {
+    doTestRandom(10000);
+  }
+
+  @Nightly
+  public void testRandomBig() throws Exception {
+    doTestRandom(200000);
+  }
+
+  private void doTestRandom(int count) throws Exception {
+    int numPoints = atLeast(count);
+
+    if (VERBOSE) {
+      System.err.println("TEST: numPoints=" + numPoints);
+    }
+
+    double[] lats = new double[numPoints];
+    double[] lons = new double[numPoints];
+
+    boolean haveRealDoc = false;
+
+    for (int docID=0;docID<numPoints;docID++) {
+      int x = random().nextInt(20);
+      if (x == 17) {
+        // Some docs don't have a point:
+        lats[docID] = Double.NaN;
+        if (VERBOSE) {
+          System.err.println("  doc=" + docID + " is missing");
+        }
+        continue;
+      }
+
+      if (docID > 0 && x < 3 && haveRealDoc) {
+        int oldDocID;
+        while (true) {
+          oldDocID = random().nextInt(docID);
+          if (Double.isNaN(lats[oldDocID]) == false) {
+            break;
+          }
+        }
+            
+        if (x == 0) {
+          // Identical lat to old point
+          lats[docID] = lats[oldDocID];
+          lons[docID] = toRadians(randomLon());
+          if (VERBOSE) {
+            System.err.println("  doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID] + " (same lat as doc=" + oldDocID + ")");
+          }
+        } else if (x == 1) {
+          // Identical lon to old point
+          lats[docID] = toRadians(randomLat());
+          lons[docID] = lons[oldDocID];
+          if (VERBOSE) {
+            System.err.println("  doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID] + " (same lon as doc=" + oldDocID + ")");
+          }
+        } else {
+          assert x == 2;
+          // Fully identical point:
+          lats[docID] = lats[oldDocID];
+          lons[docID] = lons[oldDocID];
+          if (VERBOSE) {
+            System.err.println("  doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID] + " (same lat/lon as doc=" + oldDocID + ")");
+          }
+        }
+      } else {
+        lats[docID] = toRadians(randomLat());
+        lons[docID] = toRadians(randomLon());
+        haveRealDoc = true;
+        if (VERBOSE) {
+          System.err.println("  doc=" + docID + " lat=" + lats[docID] + " lon=" + lons[docID]);
+        }
+      }
+    }
+
+    verify(lats, lons);
+  }
+
+  private static double randomLat() {
+    if (smallBBox) {
+      return 2.0 * (random().nextDouble()-0.5);
+    } else {
+      return -90 + 180.0 * random().nextDouble();
+    }
+  }
+
+  private static double randomLon() {
+    if (smallBBox) {
+      return 2.0 * (random().nextDouble()-0.5);
+    } else {
+      return -180 + 360.0 * random().nextDouble();
+    }
+  }
+
+  // Poached from Geo3dRptTest.randomShape:
+  private static GeoShape randomShape(PlanetModel planetModel) {
+    while (true) {
+      final int shapeType = random().nextInt(4);
+      switch (shapeType) {
+      case 0: {
+        // Polygons
+        final int vertexCount = random().nextInt(3) + 3;
+        final List<GeoPoint> geoPoints = new ArrayList<>();
+        while (geoPoints.size() < vertexCount) {
+          final GeoPoint gPt = new GeoPoint(planetModel, toRadians(randomLat()), toRadians(randomLon()));
+          geoPoints.add(gPt);
+        }
+        final int convexPointIndex = random().nextInt(vertexCount);       //If we get this wrong, hopefully we get IllegalArgumentException
+        try {
+          return GeoPolygonFactory.makeGeoPolygon(planetModel, geoPoints, convexPointIndex);
+        } catch (IllegalArgumentException e) {
+          // This is what happens when we create a shape that is invalid.  Although it is conceivable that there are cases where
+          // the exception is thrown incorrectly, we aren't going to be able to do that in this random test.
+          continue;
+        }
+      }
+
+      case 1: {
+        // Circles
+
+        double lat = toRadians(randomLat());
+        double lon = toRadians(randomLon());
+
+        double angle;
+        if (smallBBox) {
+          angle = random().nextDouble() * Math.PI/360.0;
+        } else {
+          angle = random().nextDouble() * Math.PI/2.0;
+        }
+
+        try {
+          return GeoCircleFactory.makeGeoCircle(planetModel, lat, lon, angle);
+        } catch (IllegalArgumentException iae) {
+          // angle is too small; try again:
+          continue;
+        }
+      }
+
+      case 2: {
+        // Rectangles
+        double lat0 = toRadians(randomLat());
+        double lat1 = toRadians(randomLat());
+        if (lat1 < lat0) {
+          double x = lat0;
+          lat0 = lat1;
+          lat1 = x;
+        }
+        double lon0 = toRadians(randomLon());
+        double lon1 = toRadians(randomLon());
+        if (lon1 < lon0) {
+          double x = lon0;
+          lon0 = lon1;
+          lon1 = x;
+        }
+
+        return GeoBBoxFactory.makeGeoBBox(planetModel, lat1, lat0, lon0, lon1);
+      }
+
+      case 3: {
+        // Paths
+        final int pointCount = random().nextInt(5) + 1;
+        final double width = toRadians(random().nextInt(89)+1);
+        try {
+          final GeoPath path = new GeoPath(planetModel, width);
+          for (int i = 0; i < pointCount; i++) {
+            path.addPoint(toRadians(randomLat()), toRadians(randomLon()));
+          }
+          path.done();
+          return path;
+        } catch (IllegalArgumentException e) {
+          // This is what happens when we create a shape that is invalid.  Although it is conceivable that there are cases where
+          // the exception is thrown incorrectly, we aren't going to be able to do that in this random test.
+          continue;
+        }
+      }
+
+      default:
+        throw new IllegalStateException("Unexpected shape type");
+      }
+    }
+  }
+
+  private static void verify(double[] lats, double[] lons) throws Exception {
+    IndexWriterConfig iwc = newIndexWriterConfig();
+
+    // Else we can get O(N^2) merging:
+    int mbd = iwc.getMaxBufferedDocs();
+    if (mbd != -1 && mbd < lats.length/100) {
+      iwc.setMaxBufferedDocs(lats.length/100);
+    }
+    iwc.setCodec(getCodec());
+    Directory dir;
+    if (lats.length > 100000) {
+      dir = newFSDirectory(createTempDir("TestBKDTree"));
+    } else {
+      dir = getDirectory();
+    }
+    Set<Integer> deleted = new HashSet<>();
+    // RandomIndexWriter is too slow here:
+    IndexWriter w = new IndexWriter(dir, iwc);
+    for(int id=0;id<lats.length;id++) {
+      Document doc = new Document();
+      doc.add(newStringField("id", ""+id, Field.Store.NO));
+      doc.add(new NumericDocValuesField("id", id));
+      if (Double.isNaN(lats[id]) == false) {
+        doc.add(new Geo3DPoint("point", lats[id], lons[id]));
+      }
+      w.addDocument(doc);
+      if (id > 0 && random().nextInt(100) == 42) {
+        int idToDelete = random().nextInt(id);
+        w.deleteDocuments(new Term("id", ""+idToDelete));
+        deleted.add(idToDelete);
+        if (VERBOSE) {
+          System.err.println("  delete id=" + idToDelete);
+        }
+      }
+    }
+    if (random().nextBoolean()) {
+      w.forceMerge(1);
+    }
+    final IndexReader r = DirectoryReader.open(w);
+    w.close();
+
+    // We can't wrap with "exotic" readers because the geo3d query must see the Geo3DDVFormat:
+    IndexSearcher s = newSearcher(r, false);
+
+    int numThreads = TestUtil.nextInt(random(), 2, 5);
+
+    List<Thread> threads = new ArrayList<>();
+    final int iters = atLeast(100);
+
+    final CountDownLatch startingGun = new CountDownLatch(1);
+    final AtomicBoolean failed = new AtomicBoolean();
+
+    for(int i=0;i<numThreads;i++) {
+      Thread thread = new Thread() {
+          @Override
+          public void run() {
+            try {
+              _run();
+            } catch (Exception e) {
+              failed.set(true);
+              throw new RuntimeException(e);
+            }
+          }
+
+          private void _run() throws Exception {
+            startingGun.await();
+
+            NumericDocValues docIDToID = MultiDocValues.getNumericValues(r, "id");
+
+            for (int iter=0;iter<iters && failed.get() == false;iter++) {
+
+              GeoShape shape = randomShape(PlanetModel.WGS84);
+
+              if (VERBOSE) {
+                System.err.println("\n" + Thread.currentThread() + ": TEST: iter=" + iter + " shape="+shape);
+              }
+              
+              Query query = Geo3DPoint.newShapeQuery("point", shape);
+
+              if (VERBOSE) {
+                System.err.println("  using query: " + query);
+              }
+
+              final FixedBitSet hits = new FixedBitSet(r.maxDoc());
+
+              s.search(query, new SimpleCollector() {
+
+                  private int docBase;
+
+                  @Override
+                  public boolean needsScores() {
+                    return false;
+                  }
+
+                  @Override
+                  protected void doSetNextReader(LeafReaderContext context) throws IOException {
+                    docBase = context.docBase;
+                  }
+
+                  @Override
+                  public void collect(int doc) {
+                    hits.set(docBase+doc);
+                  }
+                });
+
+              if (VERBOSE) {
+                System.err.println("  hitCount: " + hits.cardinality());
+              }
+      
+              for(int docID=0;docID<r.maxDoc();docID++) {
+                int id = (int) docIDToID.get(docID);
+                if (Double.isNaN(lats[id]) == false) {
+
+                  // Accurate point:
+                  GeoPoint point1 = new GeoPoint(PlanetModel.WGS84, lats[id], lons[id]);
+
+                  // Quantized point (32 bits per dim):
+                  GeoPoint point2 = quantize(PlanetModel.WGS84.getMaximumMagnitude(), point1);
+
+                  if (shape.isWithin(point1) != shape.isWithin(point2)) {
+                    if (VERBOSE) {
+                      System.out.println("  skip checking docID=" + docID + " quantization changed the expected result from " + shape.isWithin(point1) + " to " + shape.isWithin(point2));
+                    }
+                    continue;
+                  }
+
+                  boolean expected = ((deleted.contains(id) == false) && shape.isWithin(point2));
+                  if (hits.get(docID) != expected) {
+                    fail(Thread.currentThread().getName() + ": iter=" + iter + " id=" + id + " docID=" + docID + " lat=" + lats[id] + " lon=" + lons[id] + " expected " + expected + " but got: " + hits.get(docID) + " deleted?=" + deleted.contains(id) + "\n  point1=" + point1 + ", iswithin="+shape.isWithin(point1)+"\n  point2=" + point2 + ", iswithin="+shape.isWithin(point2) + "\n  query=" + query);
+                  }
+                } else {
+                  assertFalse(hits.get(docID));
+                }
+
+              }
+            }
+          }
+        };
+      thread.setName("T" + i);
+      thread.start();
+      threads.add(thread);
+    }
+    startingGun.countDown();
+    for(Thread thread : threads) {
+      thread.join();
+    }
+    IOUtils.close(r, dir);
+  }
+
+  public void testToString() {
+    Geo3DPoint point = new Geo3DPoint("point", toRadians(44.244272), toRadians(7.769736));
+    assertEquals("Geo3DPoint <point: x=0.9248467864160119 y=0.06280434265368656 z=0.37682349005486243>", point.toString());
+  }
+
+  public void testShapeQueryToString() {
+    assertEquals("PointInGeo3DShapeQuery: field=point: Shape: GeoStandardCircle: {planetmodel=PlanetModel.WGS84, center=[lat=0.3861041107739683, lon=0.06780373760536706], radius=0.1(5.729577951308232)}",
+                 Geo3DPoint.newShapeQuery("point", GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84, toRadians(44.244272), toRadians(7.769736), 0.1)).toString());
+  }
+
+  private static Directory getDirectory() {     
+    return newDirectory();
+  }
+}


[14/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoRectangle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoRectangle.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoRectangle.java
new file mode 100755
index 0000000..1420c11
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoRectangle.java
@@ -0,0 +1,288 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Bounding box limited on four sides (top lat, bottom lat, left lon, right lon).
+ * The left-right maximum extent for this shape is PI; for anything larger, use
+ * GeoWideRectangle.
+ *
+ * @lucene.internal
+ */
+public class GeoRectangle extends GeoBaseBBox {
+  /** The top latitude of the rect */
+  protected final double topLat;
+  /** The bottom latitude of the rect */
+  protected final double bottomLat;
+  /** The left longitude of the rect */
+  protected final double leftLon;
+  /** The right longitude of the rect */
+  protected final double rightLon;
+  /** The cosine of a middle latitude */
+  protected final double cosMiddleLat;
+
+  /** The upper left hand corner point */
+  protected final GeoPoint ULHC;
+  /** The upper right hand corner point */
+  protected final GeoPoint URHC;
+  /** The lower right hand corner point */
+  protected final GeoPoint LRHC;
+  /** The lower left hand corner point */
+  protected final GeoPoint LLHC;
+
+  /** The top plane */
+  protected final SidedPlane topPlane;
+  /** The bottom plane */
+  protected final SidedPlane bottomPlane;
+  /** The left plane */
+  protected final SidedPlane leftPlane;
+  /** The right plane */
+  protected final SidedPlane rightPlane;
+
+  /** Notable points for the top plane */
+  protected final GeoPoint[] topPlanePoints;
+  /** Notable points for the bottom plane */
+  protected final GeoPoint[] bottomPlanePoints;
+  /** Notable points for the left plane */
+  protected final GeoPoint[] leftPlanePoints;
+  /** Notable points for the right plane */
+  protected final GeoPoint[] rightPlanePoints;
+
+  /** Center point */
+  protected final GeoPoint centerPoint;
+
+  /** Edge point for this rectangle */
+  protected final GeoPoint[] edgePoints;
+
+  /**
+   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
+   *@param planetModel is the planet model.
+   *@param topLat is the top latitude.
+   *@param bottomLat is the bottom latitude.
+   *@param leftLon is the left longitude.
+   *@param rightLon is the right longitude.
+   */
+  public GeoRectangle(final PlanetModel planetModel, final double topLat, final double bottomLat, final double leftLon, double rightLon) {
+    super(planetModel);
+    // Argument checking
+    if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
+      throw new IllegalArgumentException("Top latitude out of range");
+    if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
+      throw new IllegalArgumentException("Bottom latitude out of range");
+    if (topLat < bottomLat)
+      throw new IllegalArgumentException("Top latitude less than bottom latitude");
+    if (leftLon < -Math.PI || leftLon > Math.PI)
+      throw new IllegalArgumentException("Left longitude out of range");
+    if (rightLon < -Math.PI || rightLon > Math.PI)
+      throw new IllegalArgumentException("Right longitude out of range");
+    double extent = rightLon - leftLon;
+    if (extent < 0.0) {
+      extent += 2.0 * Math.PI;
+    }
+    if (extent > Math.PI)
+      throw new IllegalArgumentException("Width of rectangle too great");
+
+    this.topLat = topLat;
+    this.bottomLat = bottomLat;
+    this.leftLon = leftLon;
+    this.rightLon = rightLon;
+
+    final double sinTopLat = Math.sin(topLat);
+    final double cosTopLat = Math.cos(topLat);
+    final double sinBottomLat = Math.sin(bottomLat);
+    final double cosBottomLat = Math.cos(bottomLat);
+    final double sinLeftLon = Math.sin(leftLon);
+    final double cosLeftLon = Math.cos(leftLon);
+    final double sinRightLon = Math.sin(rightLon);
+    final double cosRightLon = Math.cos(rightLon);
+
+    // Now build the four points
+    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);
+    this.cosMiddleLat = Math.cos(middleLat);
+    // Normalize
+    while (leftLon > rightLon) {
+      rightLon += Math.PI * 2.0;
+    }
+    final double middleLon = (leftLon + rightLon) * 0.5;
+    final double sinMiddleLon = Math.sin(middleLon);
+    final double cosMiddleLon = Math.cos(middleLon);
+
+    this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
+
+    this.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
+    this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
+    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
+    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
+
+    this.topPlanePoints = new GeoPoint[]{ULHC, URHC};
+    this.bottomPlanePoints = new GeoPoint[]{LLHC, LRHC};
+    this.leftPlanePoints = new GeoPoint[]{ULHC, LLHC};
+    this.rightPlanePoints = new GeoPoint[]{URHC, LRHC};
+
+    this.edgePoints = new GeoPoint[]{ULHC};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    final double newTopLat = topLat + angle;
+    final double newBottomLat = bottomLat - angle;
+    // Figuring out when we escalate to a special case requires some prefiguring
+    double currentLonSpan = rightLon - leftLon;
+    if (currentLonSpan < 0.0)
+      currentLonSpan += Math.PI * 2.0;
+    double newLeftLon = leftLon - angle;
+    double newRightLon = rightLon + angle;
+    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
+      newLeftLon = -Math.PI;
+      newRightLon = Math.PI;
+    }
+    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return topPlane.isWithin(x, y, z) &&
+        bottomPlane.isWithin(x, y, z) &&
+        leftPlane.isWithin(x, y, z) &&
+        rightPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public double getRadius() {
+    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
+    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
+    // the distance to the right or left edge from the center.
+    final double centerAngle = (rightLon - (rightLon + leftLon) * 0.5) * cosMiddleLat;
+    final double topAngle = centerPoint.arcDistance(URHC);
+    final double bottomAngle = centerPoint.arcDistance(LLHC);
+    return Math.max(centerAngle, Math.max(topAngle, bottomAngle));
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    return centerPoint;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, bottomPlane, leftPlane, rightPlane) ||
+        p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, topPlane, leftPlane, rightPlane) ||
+        p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, topPlane, bottomPlane) ||
+        p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, topPlane, bottomPlane);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(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
+  public int getRelationship(final GeoShape path) {
+    //System.err.println(this+" getrelationship with "+path);
+    final int insideRectangle = isShapeInsideBBox(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some inside");
+      return OVERLAPS;
+    }
+
+    final boolean insideShape = path.isWithin(ULHC);
+
+    if (insideRectangle == ALL_INSIDE && insideShape) {
+      //System.err.println(" inside of each other");
+      return OVERLAPS;
+    }
+
+    if (path.intersects(topPlane, topPlanePoints, bottomPlane, leftPlane, rightPlane) ||
+        path.intersects(bottomPlane, bottomPlanePoints, topPlane, leftPlane, rightPlane) ||
+        path.intersects(leftPlane, leftPlanePoints, topPlane, bottomPlane, rightPlane) ||
+        path.intersects(rightPlane, rightPlanePoints, leftPlane, topPlane, bottomPlane)) {
+      //System.err.println(" edges intersect");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      //System.err.println(" shape inside rectangle");
+      return WITHIN;
+    }
+
+    if (insideShape) {
+      //System.err.println(" shape contains rectangle");
+      return CONTAINS;
+    }
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @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, leftPlane, rightPlane);
+    final double bottomDistance = distanceStyle.computeDistance(planetModel, bottomPlane, x,y,z, topPlane, leftPlane, rightPlane);
+    final double leftDistance = distanceStyle.computeDistance(planetModel, leftPlane, x,y,z, rightPlane, topPlane, bottomPlane);
+    final double rightDistance = distanceStyle.computeDistance(planetModel, rightPlane, x,y,z, leftPlane, topPlane, bottomPlane);
+    
+    final double ULHCDistance = distanceStyle.computeDistance(ULHC, x,y,z);
+    final double URHCDistance = distanceStyle.computeDistance(URHC, x,y,z);
+    final double LRHCDistance = distanceStyle.computeDistance(LRHC, x,y,z);
+    final double LLHCDistance = distanceStyle.computeDistance(LLHC, x,y,z);
+    
+    return Math.min(
+      Math.min(
+        Math.min(topDistance, bottomDistance),
+        Math.min(leftDistance, rightDistance)),
+      Math.min(
+        Math.min(ULHCDistance, URHCDistance),
+        Math.min(LRHCDistance, LLHCDistance)));
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof GeoRectangle))
+      return false;
+    GeoRectangle other = (GeoRectangle) o;
+    return super.equals(other) && other.ULHC.equals(ULHC) && other.LRHC.equals(LRHC);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result  + ULHC.hashCode();
+    result = 31 * result  + LRHC.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoRectangle: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
+  }
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoShape.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoShape.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoShape.java
new file mode 100755
index 0000000..a2d3947
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoShape.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Generic shape.  This describes methods that help GeoAreas figure out
+ * how they interact with a shape, for the purposes of coming up with a
+ * set of geo hash values.
+ *
+ * @lucene.experimental
+ */
+public interface GeoShape extends Membership {
+
+  /**
+   * Return a sample point that is on the outside edge/boundary of the shape.
+   *
+   * @return samples of all edge points from distinct edge sections.  Typically one point
+   * is returned, but zero or two are also possible.
+   */
+  public GeoPoint[] getEdgePoints();
+
+  /**
+   * Assess whether a plane, within the provided bounds, intersects
+   * with the shape.  Note well that this method is allowed to return "true"
+   * if there are internal edges of a composite shape which intersect the plane.
+   * Doing this can cause getRelationship() for most GeoBBox shapes to return
+   * OVERLAPS rather than the more correct CONTAINS, but that cannot be
+   * helped for some complex shapes that are built out of overlapping parts.
+   *
+   * @param plane         is the plane to assess for intersection with the shape's edges or
+   *                      bounding curves.
+   * @param notablePoints represents the intersections of the plane with the supplied
+   *                      bounds.  These are used to disambiguate when two planes are identical and it needs
+   *                      to be determined whether any points exist that fulfill all the bounds.
+   * @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.
+   */
+  public boolean intersects(final Plane plane, final GeoPoint[] notablePoints, final Membership... bounds);
+
+  /**
+   * Compute bounds for the shape.
+   *
+   * @param bounds is the input bounds object.
+   *             The input object will be modified.
+   */
+  public void getBounds(final Bounds bounds);
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoSizeable.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoSizeable.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoSizeable.java
new file mode 100755
index 0000000..3c7e2ef
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoSizeable.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Some shapes can compute radii of a geocircle in which they are inscribed.
+ *
+ * @lucene.experimental
+ */
+public interface GeoSizeable {
+  /**
+   * Returns the radius of a circle into which the GeoSizeable area can
+   * be inscribed.
+   *
+   * @return the radius.
+   */
+  public double getRadius();
+
+  /**
+   * Returns the center of a circle into which the area will be inscribed.
+   *
+   * @return the center.
+   */
+  public GeoPoint getCenter();
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoSouthLatitudeZone.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoSouthLatitudeZone.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoSouthLatitudeZone.java
new file mode 100644
index 0000000..a1d8967
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoSouthLatitudeZone.java
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * This GeoBBox represents an area rectangle limited only in north latitude.
+ *
+ * @lucene.internal
+ */
+public class GeoSouthLatitudeZone extends GeoBaseBBox {
+  /** The top latitude of the zone */
+  protected final double topLat;
+  /** The cosine of the top latitude of the zone */
+  protected final double cosTopLat;
+  /** The top plane of the zone */
+  protected final SidedPlane topPlane;
+  /** An interior point of the zone */
+  protected final GeoPoint interiorPoint;
+  /** Notable points for the plane (none) */
+  protected final static GeoPoint[] planePoints = new GeoPoint[0];
+  /** A point on the top boundary */
+  protected final GeoPoint topBoundaryPoint;
+  /** Edge points; a reference to the topBoundaryPoint */
+  protected final GeoPoint[] edgePoints;
+
+  /** Constructor.
+   *@param planetModel is the planet model.
+   *@param topLat is the top latitude of the zone.
+   */
+  public GeoSouthLatitudeZone(final PlanetModel planetModel, final double topLat) {
+    super(planetModel);
+    this.topLat = topLat;
+
+    final double sinTopLat = Math.sin(topLat);
+    this.cosTopLat = Math.cos(topLat);
+
+    // Compute an interior point.  Pick one whose lat is between top and bottom.
+    final double middleLat = (topLat - Math.PI * 0.5) * 0.5;
+    final double sinMiddleLat = Math.sin(middleLat);
+    this.interiorPoint = new GeoPoint(planetModel, sinMiddleLat, 0.0, Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 1.0);
+    this.topBoundaryPoint = new GeoPoint(planetModel, sinTopLat, 0.0, Math.sqrt(1.0 - sinTopLat * sinTopLat), 1.0);
+
+    this.topPlane = new SidedPlane(interiorPoint, planetModel, sinTopLat);
+
+    this.edgePoints = new GeoPoint[]{topBoundaryPoint};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    final double newTopLat = topLat + angle;
+    final double newBottomLat = -Math.PI * 0.5;
+    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, -Math.PI, Math.PI);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return topPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public double getRadius() {
+    // This is a bit tricky.  I guess we should interpret this as meaning the angle of a circle that
+    // would contain all the bounding box points, when starting in the "center".
+    if (topLat > 0.0)
+      return Math.PI;
+    double maxCosLat = cosTopLat;
+    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;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    return p.intersects(planetModel, topPlane, notablePoints, planePoints, bounds);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds
+      .addHorizontalPlane(planetModel, topLat, topPlane);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    final int insideRectangle = isShapeInsideBBox(path);
+    if (insideRectangle == SOME_INSIDE)
+      return OVERLAPS;
+
+    final boolean insideShape = path.isWithin(topBoundaryPoint);
+
+    if (insideRectangle == ALL_INSIDE && insideShape)
+      return OVERLAPS;
+
+    // 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(topPlane, planePoints))
+      return OVERLAPS;
+
+    // There is another case for latitude zones only.  This is when the boundaries of the shape all fit
+    // within the zone, but the shape includes areas outside the zone crossing a pole.
+    // In this case, the above "overlaps" check is insufficient.  We also need to check a point on either boundary
+    // whether it is within the shape.  If both such points are within, then CONTAINS is the right answer.  If
+    // one such point is within, then OVERLAPS is the right answer.
+
+    if (insideShape)
+      return CONTAINS;
+
+    if (insideRectangle == ALL_INSIDE)
+      return WITHIN;
+
+    return DISJOINT;
+  }
+
+  @Override
+  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    return distanceStyle.computeDistance(planetModel, topPlane, x,y,z);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof GeoSouthLatitudeZone))
+      return false;
+    GeoSouthLatitudeZone other = (GeoSouthLatitudeZone) o;
+    return super.equals(other) && other.topBoundaryPoint.equals(topBoundaryPoint);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + topBoundaryPoint.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoSouthLatitudeZone: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + ")}";
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoSouthRectangle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoSouthRectangle.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoSouthRectangle.java
new file mode 100644
index 0000000..806535e
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoSouthRectangle.java
@@ -0,0 +1,259 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Bounding box limited on three sides (top lat, left lon, right lon).  The
+ * other corner is the south pole.
+ * The left-right maximum extent for this shape is PI; for anything larger, use
+ * {@link GeoWideSouthRectangle}.
+ *
+ * @lucene.internal
+ */
+public class GeoSouthRectangle extends GeoBaseBBox {
+  /** The top latitude of the rect */
+  protected final double topLat;
+  /** The left longitude of the rect */
+  protected final double leftLon;
+  /** The right longitude of the rect */
+  protected final double rightLon;
+  /** The cosine of a middle latitude */
+  protected final double cosMiddleLat;
+  /** The upper left hand corner of the rectangle */
+  protected final GeoPoint ULHC;
+  /** The upper right hand corner of the rectangle */
+  protected final GeoPoint URHC;
+
+  /** The top plane */
+  protected final SidedPlane topPlane;
+  /** The left plane */
+  protected final SidedPlane leftPlane;
+  /** The right plane */
+  protected final SidedPlane rightPlane;
+
+  /** Notable points for the top plane */
+  protected final GeoPoint[] topPlanePoints;
+  /** Notable points for the left plane */
+  protected final GeoPoint[] leftPlanePoints;
+  /** Notable points for the right plane */
+  protected final GeoPoint[] rightPlanePoints;
+
+  /** The center point */
+  protected final GeoPoint centerPoint;
+
+  /** A point on the edge */
+  protected final GeoPoint[] edgePoints;
+
+  /**
+   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
+   *@param planetModel is the planet model.
+   *@param topLat is the top latitude.
+   *@param leftLon is the left longitude.
+   *@param rightLon is the right longitude.
+   */
+  public GeoSouthRectangle(final PlanetModel planetModel, final double topLat, final double leftLon, double rightLon) {
+    super(planetModel);
+    // Argument checking
+    if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
+      throw new IllegalArgumentException("Top latitude out of range");
+    if (leftLon < -Math.PI || leftLon > Math.PI)
+      throw new IllegalArgumentException("Left longitude out of range");
+    if (rightLon < -Math.PI || rightLon > Math.PI)
+      throw new IllegalArgumentException("Right longitude out of range");
+    double extent = rightLon - leftLon;
+    if (extent < 0.0) {
+      extent += 2.0 * Math.PI;
+    }
+    if (extent > Math.PI)
+      throw new IllegalArgumentException("Width of rectangle too great");
+
+    this.topLat = topLat;
+    this.leftLon = leftLon;
+    this.rightLon = rightLon;
+
+    final double sinTopLat = Math.sin(topLat);
+    final double cosTopLat = Math.cos(topLat);
+    final double sinLeftLon = Math.sin(leftLon);
+    final double cosLeftLon = Math.cos(leftLon);
+    final double sinRightLon = Math.sin(rightLon);
+    final double cosRightLon = Math.cos(rightLon);
+
+    // Now build the four points
+    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);
+    this.cosMiddleLat = Math.cos(middleLat);
+    // Normalize
+    while (leftLon > rightLon) {
+      rightLon += Math.PI * 2.0;
+    }
+    final double middleLon = (leftLon + rightLon) * 0.5;
+    final double sinMiddleLon = Math.sin(middleLon);
+    final double cosMiddleLon = Math.cos(middleLon);
+
+    this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
+
+    this.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
+    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
+    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
+
+    this.topPlanePoints = new GeoPoint[]{ULHC, URHC};
+    this.leftPlanePoints = new GeoPoint[]{ULHC, planetModel.SOUTH_POLE};
+    this.rightPlanePoints = new GeoPoint[]{URHC, planetModel.SOUTH_POLE};
+    
+    this.edgePoints = new GeoPoint[]{planetModel.SOUTH_POLE};
+
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    final double newTopLat = topLat + angle;
+    final double newBottomLat = -Math.PI * 0.5;
+    // Figuring out when we escalate to a special case requires some prefiguring
+    double currentLonSpan = rightLon - leftLon;
+    if (currentLonSpan < 0.0)
+      currentLonSpan += Math.PI * 2.0;
+    double newLeftLon = leftLon - angle;
+    double newRightLon = rightLon + angle;
+    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
+      newLeftLon = -Math.PI;
+      newRightLon = Math.PI;
+    }
+    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return topPlane.isWithin(x, y, z) &&
+        leftPlane.isWithin(x, y, z) &&
+        rightPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public double getRadius() {
+    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
+    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
+    // the distance to the right or left edge from the center.
+    final double centerAngle = (rightLon - (rightLon + leftLon) * 0.5) * cosMiddleLat;
+    final double topAngle = centerPoint.arcDistance(URHC);
+    return Math.max(centerAngle, topAngle);
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    return centerPoint;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, leftPlane, rightPlane) ||
+        p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, topPlane) ||
+        p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, topPlane);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds
+      .addHorizontalPlane(planetModel, topLat, topPlane, leftPlane, rightPlane)
+      .addVerticalPlane(planetModel, leftLon, leftPlane, topPlane, rightPlane)
+      .addVerticalPlane(planetModel, rightLon, rightPlane, topPlane, leftPlane)
+      .addPoint(URHC).addPoint(ULHC).addPoint(planetModel.SOUTH_POLE);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    //System.err.println(this+" getrelationship with "+path);
+    final int insideRectangle = isShapeInsideBBox(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some inside");
+      return OVERLAPS;
+    }
+
+    final boolean insideShape = path.isWithin(planetModel.SOUTH_POLE);
+
+    if (insideRectangle == ALL_INSIDE && insideShape) {
+      //System.err.println(" inside of each other");
+      return OVERLAPS;
+    }
+
+    if (path.intersects(topPlane, topPlanePoints, leftPlane, rightPlane) ||
+        path.intersects(leftPlane, leftPlanePoints, topPlane, rightPlane) ||
+        path.intersects(rightPlane, rightPlanePoints, leftPlane, topPlane)) {
+      //System.err.println(" edges intersect");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      //System.err.println(" shape inside rectangle");
+      return WITHIN;
+    }
+
+    if (insideShape) {
+      //System.err.println(" shape contains rectangle");
+      return CONTAINS;
+    }
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @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, leftPlane, rightPlane);
+    final double leftDistance = distanceStyle.computeDistance(planetModel, leftPlane, x,y,z, rightPlane, topPlane);
+    final double rightDistance = distanceStyle.computeDistance(planetModel, rightPlane, x,y,z, leftPlane, topPlane);
+    
+    final double ULHCDistance = distanceStyle.computeDistance(ULHC, x,y,z);
+    final double URHCDistance = distanceStyle.computeDistance(URHC, x,y,z);
+    
+    return Math.min(
+      Math.min(
+        topDistance,
+        Math.min(leftDistance, rightDistance)),
+      Math.min(ULHCDistance, URHCDistance));
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof GeoSouthRectangle))
+      return false;
+    GeoSouthRectangle other = (GeoSouthRectangle) o;
+    return super.equals(other) && other.ULHC.equals(ULHC) && other.URHC.equals(URHC);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + ULHC.hashCode();
+    result = 31 * result + URHC.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoSouthRectangle: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
+  }
+}
+  
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoStandardCircle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoStandardCircle.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoStandardCircle.java
new file mode 100755
index 0000000..bbf5046
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoStandardCircle.java
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Circular area with a center and radius.
+ *
+ * @lucene.experimental
+ */
+public class GeoStandardCircle extends GeoBaseCircle {
+  /** Center of circle */
+  protected final GeoPoint center;
+  /** Cutoff angle of circle (not quite the same thing as radius) */
+  protected final double cutoffAngle;
+  /** The plane describing the circle (really an ellipse on a non-spherical world) */
+  protected final SidedPlane circlePlane;
+  /** A point that is on the world and on the circle plane */
+  protected final GeoPoint[] edgePoints;
+  /** Notable points for a circle -- there aren't any */
+  protected static final GeoPoint[] circlePoints = new GeoPoint[0];
+
+  /** Constructor.
+   *@param planetModel is the planet model.
+   *@param lat is the center latitude.
+   *@param lon is the center longitude.
+   *@param cutoffAngle is the cutoff angle for the circle.
+   */
+  public GeoStandardCircle(final PlanetModel planetModel, final double lat, final double lon, final double cutoffAngle) {
+    super(planetModel);
+    if (lat < -Math.PI * 0.5 || lat > Math.PI * 0.5)
+      throw new IllegalArgumentException("Latitude out of bounds");
+    if (lon < -Math.PI || lon > Math.PI)
+      throw new IllegalArgumentException("Longitude out of bounds");
+    if (cutoffAngle < 0.0 || cutoffAngle > Math.PI)
+      throw new IllegalArgumentException("Cutoff angle out of bounds");
+    if (cutoffAngle < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("Cutoff angle cannot be effectively zero");
+    this.center = new GeoPoint(planetModel, lat, lon);
+    // In an ellipsoidal world, cutoff distances make no sense, unfortunately.  Only membership
+    // can be used to make in/out determination.
+    this.cutoffAngle = cutoffAngle;
+    // Compute two points on the circle, with the right angle from the center.  We'll use these
+    // to obtain the perpendicular plane to the circle.
+    double upperLat = lat + cutoffAngle;
+    double upperLon = lon;
+    if (upperLat > Math.PI * 0.5) {
+      upperLon += Math.PI;
+      if (upperLon > Math.PI)
+        upperLon -= 2.0 * Math.PI;
+      upperLat = Math.PI - upperLat;
+    }
+    double lowerLat = lat - cutoffAngle;
+    double lowerLon = lon;
+    if (lowerLat < -Math.PI * 0.5) {
+      lowerLon += Math.PI;
+      if (lowerLon > Math.PI)
+        lowerLon -= 2.0 * Math.PI;
+      lowerLat = -Math.PI - lowerLat;
+    }
+    final GeoPoint upperPoint = new GeoPoint(planetModel, upperLat, upperLon);
+    final GeoPoint lowerPoint = new GeoPoint(planetModel, lowerLat, lowerLon);
+    if (Math.abs(cutoffAngle - Math.PI) < Vector.MINIMUM_RESOLUTION) {
+      // Circle is the whole world
+      this.circlePlane = null;
+      this.edgePoints = new GeoPoint[0];
+    } else {
+      // Construct normal plane
+      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)
+        throw new IllegalArgumentException("Couldn't construct circle plane, probably too small?  Cutoff angle = "+cutoffAngle+"; upperPoint = "+upperPoint+"; lowerPoint = "+lowerPoint);
+      final GeoPoint recomputedIntersectionPoint = circlePlane.getSampleIntersectionPoint(planetModel, normalPlane);
+      if (recomputedIntersectionPoint == null)
+        throw new IllegalArgumentException("Couldn't construct intersection point, probably circle too small?  Plane = "+circlePlane);
+      this.edgePoints = new GeoPoint[]{recomputedIntersectionPoint};
+    }
+  }
+
+  @Override
+  public double getRadius() {
+    return cutoffAngle;
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    return center;
+  }
+
+  @Override
+  protected double distance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    return distanceStyle.computeDistance(this.center, x, y, z);
+  }
+
+  @Override
+  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    return distanceStyle.computeDistance(planetModel, circlePlane, x, y, z);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    if (circlePlane == null) {
+      return true;
+    }
+    // Fastest way of determining membership
+    return circlePlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    if (circlePlane == null) {
+      return false;
+    }
+    return circlePlane.intersects(planetModel, p, notablePoints, circlePoints, bounds);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    if (circlePlane == null) {
+      // Entire world; should already be covered
+      return;
+    }
+    bounds.addPoint(center);
+    bounds.addPlane(planetModel, circlePlane);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof GeoStandardCircle))
+      return false;
+    GeoStandardCircle other = (GeoStandardCircle) o;
+    return super.equals(other) && other.center.equals(center) && other.cutoffAngle == cutoffAngle;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + center.hashCode();
+    long temp = Double.doubleToLongBits(cutoffAngle);
+    result = 31 * result + (int) (temp ^ (temp >>> 32));
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoStandardCircle: {planetmodel=" + planetModel+", center=" + center + ", radius=" + cutoffAngle + "(" + cutoffAngle * 180.0 / Math.PI + ")}";
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideDegenerateHorizontalLine.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideDegenerateHorizontalLine.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideDegenerateHorizontalLine.java
new file mode 100644
index 0000000..48a73af
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideDegenerateHorizontalLine.java
@@ -0,0 +1,238 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Degenerate bounding box wider than PI and limited on two sides (left lon, right lon).
+ *
+ * @lucene.internal
+ */
+public class GeoWideDegenerateHorizontalLine extends GeoBaseBBox {
+  /** The latitude of the line */
+  protected final double latitude;
+  /** The left longitude cutoff of the line */
+  protected final double leftLon;
+  /** The right longitude cutoff of the line */
+  protected final double rightLon;
+
+  /** The left end of the line */
+  protected final GeoPoint LHC;
+  /** The right end of the line */
+  protected final GeoPoint RHC;
+
+  /** The plane the line is in */
+  protected final Plane plane;
+  /** The left cutoff plane */
+  protected final SidedPlane leftPlane;
+  /** The right cutoff plane */
+  protected final SidedPlane rightPlane;
+
+  /** Notable points for the line */
+  protected final GeoPoint[] planePoints;
+
+  /** Center point for the line */
+  protected final GeoPoint centerPoint;
+
+  /** Left/right combination bound */
+  protected final EitherBound eitherBound;
+
+  /** A point on the line */
+  protected final GeoPoint[] edgePoints;
+
+  /**
+   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}.
+   * Horizontal angle must be greater than or equal to PI.
+   *@param planetModel is the planet model.
+   *@param latitude is the line latitude.
+   *@param leftLon is the left cutoff longitude.
+   *@param rightLon is the right cutoff longitude.
+   */
+  public GeoWideDegenerateHorizontalLine(final PlanetModel planetModel, final double latitude, final double leftLon, double rightLon) {
+    super(planetModel);
+    // Argument checking
+    if (latitude > Math.PI * 0.5 || latitude < -Math.PI * 0.5)
+      throw new IllegalArgumentException("Latitude out of range");
+    if (leftLon < -Math.PI || leftLon > Math.PI)
+      throw new IllegalArgumentException("Left longitude out of range");
+    if (rightLon < -Math.PI || rightLon > Math.PI)
+      throw new IllegalArgumentException("Right longitude out of range");
+    double extent = rightLon - leftLon;
+    if (extent < 0.0) {
+      extent += 2.0 * Math.PI;
+    }
+    if (extent < Math.PI)
+      throw new IllegalArgumentException("Width of rectangle too small");
+
+    this.latitude = latitude;
+    this.leftLon = leftLon;
+    this.rightLon = rightLon;
+
+    final double sinLatitude = Math.sin(latitude);
+    final double cosLatitude = Math.cos(latitude);
+    final double sinLeftLon = Math.sin(leftLon);
+    final double cosLeftLon = Math.cos(leftLon);
+    final double sinRightLon = Math.sin(rightLon);
+    final double cosRightLon = Math.cos(rightLon);
+
+    // Now build the two points
+    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);
+
+    // Normalize
+    while (leftLon > rightLon) {
+      rightLon += Math.PI * 2.0;
+    }
+    double middleLon = (leftLon + rightLon) * 0.5;
+    double sinMiddleLon = Math.sin(middleLon);
+    double cosMiddleLon = Math.cos(middleLon);
+
+    this.centerPoint = new GeoPoint(planetModel, sinLatitude, sinMiddleLon, cosLatitude, cosMiddleLon);
+
+    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
+    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
+
+    this.planePoints = new GeoPoint[]{LHC, RHC};
+
+    this.eitherBound = new EitherBound();
+
+    this.edgePoints = new GeoPoint[]{centerPoint};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    final double newTopLat = latitude + angle;
+    final double newBottomLat = latitude - angle;
+    // Figuring out when we escalate to a special case requires some prefiguring
+    double currentLonSpan = rightLon - leftLon;
+    if (currentLonSpan < 0.0)
+      currentLonSpan += Math.PI * 2.0;
+    double newLeftLon = leftLon - angle;
+    double newRightLon = rightLon + angle;
+    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
+      newLeftLon = -Math.PI;
+      newRightLon = Math.PI;
+    }
+    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return plane.evaluateIsZero(x, y, z) &&
+        (leftPlane.isWithin(x, y, z) ||
+            rightPlane.isWithin(x, y, z));
+  }
+
+  @Override
+  public double getRadius() {
+    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
+    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
+    // the distance to the right or left edge from the center.
+    final double topAngle = centerPoint.arcDistance(RHC);
+    final double bottomAngle = centerPoint.arcDistance(LHC);
+    return Math.max(topAngle, bottomAngle);
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    return centerPoint;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    // Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
+    // requires crossing into the right part of the other.  So intersection can ignore the left/right bounds.
+    return p.intersects(planetModel, plane, notablePoints, planePoints, bounds, eitherBound);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds.isWide()
+      .addHorizontalPlane(planetModel, latitude, plane, eitherBound)
+      .addPoint(LHC)
+      .addPoint(RHC);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    if (path.intersects(plane, planePoints, eitherBound)) {
+      return OVERLAPS;
+    }
+
+    if (path.isWithin(centerPoint)) {
+      return CONTAINS;
+    }
+
+    return DISJOINT;
+  }
+
+  @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, eitherBound);
+    
+    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 GeoWideDegenerateHorizontalLine))
+      return false;
+    GeoWideDegenerateHorizontalLine other = (GeoWideDegenerateHorizontalLine) o;
+    return super.equals(other) && other.LHC.equals(LHC) && other.RHC.equals(RHC);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + LHC.hashCode();
+    result = 31 * result + RHC.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoWideDegenerateHorizontalLine: {planetmodel="+planetModel+", latitude=" + latitude + "(" + latitude * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightLon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
+  }
+
+  /** Membership implementation representing a wide cutoff (more than 180 degrees).
+   */
+  protected class EitherBound implements Membership {
+    /** Constructor.
+     */
+    public EitherBound() {
+    }
+
+    @Override
+    public boolean isWithin(final double x, final double y, final double z) {
+      return leftPlane.isWithin(x, y, z) || rightPlane.isWithin(x, y, z);
+    }
+  }
+}
+  
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideLongitudeSlice.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideLongitudeSlice.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideLongitudeSlice.java
new file mode 100755
index 0000000..1d61876
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideLongitudeSlice.java
@@ -0,0 +1,208 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Bounding box wider than PI but limited on left and right sides (
+ * left lon, right lon).
+ *
+ * @lucene.internal
+ */
+public class GeoWideLongitudeSlice extends GeoBaseBBox {
+  /** The left longitude */
+  protected final double leftLon;
+  /** The right longitude */
+  protected final double rightLon;
+
+  /** The left plane */
+  protected final SidedPlane leftPlane;
+  /** The right plane */
+  protected final SidedPlane rightPlane;
+
+  /** Notable points for the shape */
+  protected final GeoPoint[] planePoints;
+
+  /** Center point for the shape */
+  protected final GeoPoint centerPoint;
+
+  /** A point on the edge of the shape */
+  protected final GeoPoint[] edgePoints; 
+
+  /**
+   * Accepts only values in the following ranges: lon: {@code -PI -> PI}.
+   * Horizantal angle must be greater than or equal to PI.
+   *@param planetModel is the planet model.
+   *@param leftLon is the left longitude.
+   *@param rightLon is the right longitude.
+   */
+  public GeoWideLongitudeSlice(final PlanetModel planetModel, final double leftLon, double rightLon) {
+    super(planetModel);
+    // Argument checking
+    if (leftLon < -Math.PI || leftLon > Math.PI)
+      throw new IllegalArgumentException("Left longitude out of range");
+    if (rightLon < -Math.PI || rightLon > Math.PI)
+      throw new IllegalArgumentException("Right longitude out of range");
+    double extent = rightLon - leftLon;
+    if (extent < 0.0) {
+      extent += 2.0 * Math.PI;
+    }
+    if (extent < Math.PI)
+      throw new IllegalArgumentException("Width of rectangle too small");
+
+    this.leftLon = leftLon;
+    this.rightLon = rightLon;
+
+    final double sinLeftLon = Math.sin(leftLon);
+    final double cosLeftLon = Math.cos(leftLon);
+    final double sinRightLon = Math.sin(rightLon);
+    final double cosRightLon = Math.cos(rightLon);
+
+    // Normalize
+    while (leftLon > rightLon) {
+      rightLon += Math.PI * 2.0;
+    }
+    final double middleLon = (leftLon + rightLon) * 0.5;
+    this.centerPoint = new GeoPoint(planetModel, 0.0, middleLon);
+
+    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
+    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
+    
+    this.planePoints = new GeoPoint[]{planetModel.NORTH_POLE, planetModel.SOUTH_POLE};
+    this.edgePoints = new GeoPoint[]{planetModel.NORTH_POLE};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    // Figuring out when we escalate to a special case requires some prefiguring
+    double currentLonSpan = rightLon - leftLon;
+    if (currentLonSpan < 0.0)
+      currentLonSpan += Math.PI * 2.0;
+    double newLeftLon = leftLon - angle;
+    double newRightLon = rightLon + angle;
+    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
+      newLeftLon = -Math.PI;
+      newRightLon = Math.PI;
+    }
+    return GeoBBoxFactory.makeGeoBBox(planetModel, Math.PI * 0.5, -Math.PI * 0.5, newLeftLon, newRightLon);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return leftPlane.isWithin(x, y, z) ||
+        rightPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public double getRadius() {
+    // Compute the extent and divide by two
+    double extent = rightLon - leftLon;
+    if (extent < 0.0)
+      extent += Math.PI * 2.0;
+    return Math.max(Math.PI * 0.5, extent * 0.5);
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    return centerPoint;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    // Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
+    // requires crossing into the right part of the other.  So intersection can ignore the left/right bounds.
+    return p.intersects(planetModel, leftPlane, notablePoints, planePoints, bounds) ||
+        p.intersects(planetModel, rightPlane, notablePoints, planePoints, bounds);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds.isWide()
+      .addVerticalPlane(planetModel, leftLon, leftPlane)
+      .addVerticalPlane(planetModel, rightLon, rightPlane)
+      .addPoint(planetModel.NORTH_POLE)
+      .addPoint(planetModel.SOUTH_POLE);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    final int insideRectangle = isShapeInsideBBox(path);
+    if (insideRectangle == SOME_INSIDE)
+      return OVERLAPS;
+
+    final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
+
+    if (insideRectangle == ALL_INSIDE && insideShape)
+      return OVERLAPS;
+
+    if (path.intersects(leftPlane, planePoints) ||
+        path.intersects(rightPlane, planePoints))
+      return OVERLAPS;
+
+    if (insideRectangle == ALL_INSIDE)
+      return WITHIN;
+
+    if (insideShape)
+      return CONTAINS;
+
+    return DISJOINT;
+  }
+
+  @Override
+  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    // Because the rectangle exceeds 180 degrees, it is safe to compute the horizontally 
+    // unbounded distance to both the left and the right and only take the minimum of the two.
+    final double leftDistance = distanceStyle.computeDistance(planetModel, leftPlane, x,y,z);
+    final double rightDistance = distanceStyle.computeDistance(planetModel, rightPlane, x,y,z);
+    
+    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(leftDistance, rightDistance),
+      Math.min(northDistance, southDistance));
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof GeoWideLongitudeSlice))
+      return false;
+    GeoWideLongitudeSlice other = (GeoWideLongitudeSlice) o;
+    return super.equals(other) && other.leftLon == leftLon && other.rightLon == rightLon;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    long temp = Double.doubleToLongBits(leftLon);
+    result = 31 * result + (int) (temp ^ (temp >>> 32));
+    temp = Double.doubleToLongBits(rightLon);
+    result = 31 * result + (int) (temp ^ (temp >>> 32));
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoWideLongitudeSlice: {planetmodel="+planetModel+", leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
+  }
+}
+  

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideNorthRectangle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideNorthRectangle.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideNorthRectangle.java
new file mode 100644
index 0000000..9f9dd49
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideNorthRectangle.java
@@ -0,0 +1,286 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Bounding box wider than PI but limited on three sides (
+ * bottom lat, left lon, right lon).
+ *
+ * @lucene.internal
+ */
+public class GeoWideNorthRectangle extends GeoBaseBBox {
+  /** Bottom latitude */
+  protected final double bottomLat;
+  /** Left longitude */
+  protected final double leftLon;
+  /** Right longitude */
+  protected final double rightLon;
+
+  /** The cosine of the middle latitude */
+  protected final double cosMiddleLat;
+
+  /** The lower right hand corner point */
+  protected final GeoPoint LRHC;
+  /** The lower left hand corner point */
+  protected final GeoPoint LLHC;
+
+  /** The bottom plane */
+  protected final SidedPlane bottomPlane;
+  /** The left plane */
+  protected final SidedPlane leftPlane;
+  /** The right plane */
+  protected final SidedPlane rightPlane;
+
+  /** Notable points for the bottom plane */
+  protected final GeoPoint[] bottomPlanePoints;
+  /** Notable points for the left plane */
+  protected final GeoPoint[] leftPlanePoints;
+  /** Notable points for the right plane */
+  protected final GeoPoint[] rightPlanePoints;
+
+  /** Center point */
+  protected final GeoPoint centerPoint;
+
+  /** Composite left/right bounds */
+  protected final EitherBound eitherBound;
+
+  /** A point on the edge */
+  protected final GeoPoint[] edgePoints;
+
+  /**
+   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}.
+   * Horizontal angle must be greater than or equal to PI.
+   */
+  public GeoWideNorthRectangle(final PlanetModel planetModel, final double bottomLat, final double leftLon, double rightLon) {
+    super(planetModel);
+    // Argument checking
+    if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
+      throw new IllegalArgumentException("Bottom latitude out of range");
+    if (leftLon < -Math.PI || leftLon > Math.PI)
+      throw new IllegalArgumentException("Left longitude out of range");
+    if (rightLon < -Math.PI || rightLon > Math.PI)
+      throw new IllegalArgumentException("Right longitude out of range");
+    double extent = rightLon - leftLon;
+    if (extent < 0.0) {
+      extent += 2.0 * Math.PI;
+    }
+    if (extent < Math.PI)
+      throw new IllegalArgumentException("Width of rectangle too small");
+
+    this.bottomLat = bottomLat;
+    this.leftLon = leftLon;
+    this.rightLon = rightLon;
+
+    final double sinBottomLat = Math.sin(bottomLat);
+    final double cosBottomLat = Math.cos(bottomLat);
+    final double sinLeftLon = Math.sin(leftLon);
+    final double cosLeftLon = Math.cos(leftLon);
+    final double sinRightLon = Math.sin(rightLon);
+    final double cosRightLon = Math.cos(rightLon);
+
+    // Now build the four points
+    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);
+    this.cosMiddleLat = Math.cos(middleLat);
+    // Normalize
+    while (leftLon > rightLon) {
+      rightLon += Math.PI * 2.0;
+    }
+    final double middleLon = (leftLon + rightLon) * 0.5;
+    final double sinMiddleLon = Math.sin(middleLon);
+    final double cosMiddleLon = Math.cos(middleLon);
+
+    this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
+
+    this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
+    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
+    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
+
+    this.bottomPlanePoints = new GeoPoint[]{LLHC, LRHC};
+    this.leftPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LLHC};
+    this.rightPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LRHC};
+
+    this.eitherBound = new EitherBound();
+    this.edgePoints = new GeoPoint[]{planetModel.NORTH_POLE};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    final double newTopLat = Math.PI * 0.5;
+    final double newBottomLat = bottomLat - angle;
+    // Figuring out when we escalate to a special case requires some prefiguring
+    double currentLonSpan = rightLon - leftLon;
+    if (currentLonSpan < 0.0)
+      currentLonSpan += Math.PI * 2.0;
+    double newLeftLon = leftLon - angle;
+    double newRightLon = rightLon + angle;
+    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
+      newLeftLon = -Math.PI;
+      newRightLon = Math.PI;
+    }
+    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return
+        bottomPlane.isWithin(x, y, z) &&
+            (leftPlane.isWithin(x, y, z) ||
+                rightPlane.isWithin(x, y, z));
+  }
+
+  @Override
+  public double getRadius() {
+    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
+    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
+    // the distance to the right or left edge from the center.
+    final double centerAngle = (rightLon - (rightLon + leftLon) * 0.5) * cosMiddleLat;
+    final double bottomAngle = centerPoint.arcDistance(LLHC);
+    return Math.max(centerAngle, bottomAngle);
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    return centerPoint;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    // Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
+    // requires crossing into the right part of the other.  So intersection can ignore the left/right bounds.
+    return
+        p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, eitherBound) ||
+            p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, bottomPlane) ||
+            p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, bottomPlane);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds.isWide()
+      .addHorizontalPlane(planetModel, bottomLat, bottomPlane, eitherBound)
+      .addVerticalPlane(planetModel, leftLon, leftPlane, bottomPlane)
+      .addVerticalPlane(planetModel, rightLon, rightPlane, bottomPlane)
+      .addPoint(LLHC).addPoint(LRHC).addPoint(planetModel.NORTH_POLE);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    //System.err.println(this+" comparing to "+path);
+    final int insideRectangle = isShapeInsideBBox(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some inside");
+      return OVERLAPS;
+    }
+
+    final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
+
+    if (insideRectangle == ALL_INSIDE && insideShape) {
+      //System.err.println(" both inside each other");
+      return OVERLAPS;
+    }
+
+    if (
+        path.intersects(bottomPlane, bottomPlanePoints, eitherBound) ||
+            path.intersects(leftPlane, leftPlanePoints, bottomPlane) ||
+            path.intersects(rightPlane, rightPlanePoints, bottomPlane)) {
+      //System.err.println(" edges intersect");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      //System.err.println(" shape inside rectangle");
+      return WITHIN;
+    }
+
+    if (insideShape) {
+      //System.err.println(" rectangle inside shape");
+      return CONTAINS;
+    }
+
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @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, eitherBound);
+    // Because the rectangle exceeds 180 degrees, it is safe to compute the horizontally 
+    // unbounded distance to both the left and the right and only take the minimum of the two.
+    final double leftDistance = distanceStyle.computeDistance(planetModel, leftPlane, x,y,z, bottomPlane);
+    final double rightDistance = distanceStyle.computeDistance(planetModel, rightPlane, x,y,z, bottomPlane);
+    
+    final double LRHCDistance = distanceStyle.computeDistance(LRHC, x,y,z);
+    final double LLHCDistance = distanceStyle.computeDistance(LLHC, x,y,z);
+    
+    return Math.min(
+      Math.min(
+        bottomDistance,
+        Math.min(leftDistance, rightDistance)),
+      Math.min(LRHCDistance, LLHCDistance));
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof GeoWideNorthRectangle))
+      return false;
+    GeoWideNorthRectangle other = (GeoWideNorthRectangle) o;
+    return super.equals(other) && other.LLHC.equals(LLHC) && other.LRHC.equals(LRHC);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + LLHC.hashCode();
+    result = 31 * result + LRHC.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoWideNorthRectangle: {planetmodel="+planetModel+", bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
+  }
+
+  /** Membership implementation representing a wide (more than 180 degree) bound.
+   */
+  protected class EitherBound implements Membership {
+    /** Constructor.
+     */
+    public EitherBound() {
+    }
+
+    @Override
+    public boolean isWithin(final Vector v) {
+      return leftPlane.isWithin(v) || rightPlane.isWithin(v);
+    }
+
+    @Override
+    public boolean isWithin(final double x, final double y, final double z) {
+      return leftPlane.isWithin(x, y, z) || rightPlane.isWithin(x, y, z);
+    }
+  }
+}
+  
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideRectangle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideRectangle.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideRectangle.java
new file mode 100755
index 0000000..c561747
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideRectangle.java
@@ -0,0 +1,319 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Bounding box wider than PI but limited on four sides (top lat,
+ * bottom lat, left lon, right lon).
+ *
+ * @lucene.internal
+ */
+public class GeoWideRectangle extends GeoBaseBBox {
+  /** The top latitude */
+  protected final double topLat;
+  /** The bottom latitude */
+  protected final double bottomLat;
+  /** The left longitude */
+  protected final double leftLon;
+  /** The right longitude */
+  protected final double rightLon;
+
+  /** Cosine of the middle latitude */
+  protected final double cosMiddleLat;
+
+  /** Upper left hand corner point */
+  protected final GeoPoint ULHC;
+  /** Lower right hand corner point */
+  protected final GeoPoint URHC;
+  /** Lower right hand corner point */
+  protected final GeoPoint LRHC;
+  /** Lower left hand corner point */
+  protected final GeoPoint LLHC;
+
+  /** Top plane */
+  protected final SidedPlane topPlane;
+  /** Bottom plane */
+  protected final SidedPlane bottomPlane;
+  /** Left plane */
+  protected final SidedPlane leftPlane;
+  /** Right plane */
+  protected final SidedPlane rightPlane;
+
+  /** Top plane's notable points */
+  protected final GeoPoint[] topPlanePoints;
+  /** Bottom plane's notable points */
+  protected final GeoPoint[] bottomPlanePoints;
+  /** Left plane's notable points */
+  protected final GeoPoint[] leftPlanePoints;
+  /** Right plane's notable points */
+  protected final GeoPoint[] rightPlanePoints;
+
+  /** Center point */
+  protected final GeoPoint centerPoint;
+
+  /** Combined left/right bounds */
+  protected final EitherBound eitherBound;
+
+  /** A point on the edge */
+  protected final GeoPoint[] edgePoints;
+
+  /**
+   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}.
+   * Horizontal angle must be greater than or equal to PI.
+   */
+  public GeoWideRectangle(final PlanetModel planetModel, final double topLat, final double bottomLat, final double leftLon, double rightLon) {
+    super(planetModel);
+    // Argument checking
+    if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
+      throw new IllegalArgumentException("Top latitude out of range");
+    if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
+      throw new IllegalArgumentException("Bottom latitude out of range");
+    if (topLat < bottomLat)
+      throw new IllegalArgumentException("Top latitude less than bottom latitude");
+    if (leftLon < -Math.PI || leftLon > Math.PI)
+      throw new IllegalArgumentException("Left longitude out of range");
+    if (rightLon < -Math.PI || rightLon > Math.PI)
+      throw new IllegalArgumentException("Right longitude out of range");
+    double extent = rightLon - leftLon;
+    if (extent < 0.0) {
+      extent += 2.0 * Math.PI;
+    }
+    if (extent < Math.PI)
+      throw new IllegalArgumentException("Width of rectangle too small");
+
+    this.topLat = topLat;
+    this.bottomLat = bottomLat;
+    this.leftLon = leftLon;
+    this.rightLon = rightLon;
+
+    final double sinTopLat = Math.sin(topLat);
+    final double cosTopLat = Math.cos(topLat);
+    final double sinBottomLat = Math.sin(bottomLat);
+    final double cosBottomLat = Math.cos(bottomLat);
+    final double sinLeftLon = Math.sin(leftLon);
+    final double cosLeftLon = Math.cos(leftLon);
+    final double sinRightLon = Math.sin(rightLon);
+    final double cosRightLon = Math.cos(rightLon);
+
+    // Now build the four points
+    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);
+    this.cosMiddleLat = Math.cos(middleLat);
+    // Normalize
+    while (leftLon > rightLon) {
+      rightLon += Math.PI * 2.0;
+    }
+    final double middleLon = (leftLon + rightLon) * 0.5;
+    final double sinMiddleLon = Math.sin(middleLon);
+    final double cosMiddleLon = Math.cos(middleLon);
+
+    this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
+
+    this.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
+    this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
+    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
+    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
+
+    this.topPlanePoints = new GeoPoint[]{ULHC, URHC};
+    this.bottomPlanePoints = new GeoPoint[]{LLHC, LRHC};
+    this.leftPlanePoints = new GeoPoint[]{ULHC, LLHC};
+    this.rightPlanePoints = new GeoPoint[]{URHC, LRHC};
+
+    this.eitherBound = new EitherBound();
+
+    this.edgePoints = new GeoPoint[]{ULHC};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    final double newTopLat = topLat + angle;
+    final double newBottomLat = bottomLat - angle;
+    // Figuring out when we escalate to a special case requires some prefiguring
+    double currentLonSpan = rightLon - leftLon;
+    if (currentLonSpan < 0.0)
+      currentLonSpan += Math.PI * 2.0;
+    double newLeftLon = leftLon - angle;
+    double newRightLon = rightLon + angle;
+    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
+      newLeftLon = -Math.PI;
+      newRightLon = Math.PI;
+    }
+    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return topPlane.isWithin(x, y, z) &&
+        bottomPlane.isWithin(x, y, z) &&
+        (leftPlane.isWithin(x, y, z) ||
+            rightPlane.isWithin(x, y, z));
+  }
+
+  @Override
+  public double getRadius() {
+    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
+    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
+    // the distance to the right or left edge from the center.
+    final double centerAngle = (rightLon - (rightLon + leftLon) * 0.5) * cosMiddleLat;
+    final double topAngle = centerPoint.arcDistance(URHC);
+    final double bottomAngle = centerPoint.arcDistance(LLHC);
+    return Math.max(centerAngle, Math.max(topAngle, bottomAngle));
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  /**
+   * Returns the center of a circle into which the area will be inscribed.
+   *
+   * @return the center.
+   */
+  @Override
+  public GeoPoint getCenter() {
+    return centerPoint;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    // Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
+    // requires crossing into the right part of the other.  So intersection can ignore the left/right bounds.
+    return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, bottomPlane, eitherBound) ||
+        p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, topPlane, eitherBound) ||
+        p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, topPlane, bottomPlane) ||
+        p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, topPlane, bottomPlane);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds.isWide()
+      .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
+  public int getRelationship(final GeoShape path) {
+    //System.err.println(this+" comparing to "+path);
+    final int insideRectangle = isShapeInsideBBox(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some inside");
+      return OVERLAPS;
+    }
+
+    final boolean insideShape = path.isWithin(ULHC);
+
+    if (insideRectangle == ALL_INSIDE && insideShape) {
+      //System.err.println(" both inside each other");
+      return OVERLAPS;
+    }
+
+    if (path.intersects(topPlane, topPlanePoints, bottomPlane, eitherBound) ||
+        path.intersects(bottomPlane, bottomPlanePoints, topPlane, eitherBound) ||
+        path.intersects(leftPlane, leftPlanePoints, topPlane, bottomPlane) ||
+        path.intersects(rightPlane, rightPlanePoints, topPlane, bottomPlane)) {
+      //System.err.println(" edges intersect");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      //System.err.println(" shape inside rectangle");
+      return WITHIN;
+    }
+
+    if (insideShape) {
+      //System.err.println(" rectangle inside shape");
+      return CONTAINS;
+    }
+
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @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, eitherBound);
+    final double bottomDistance = distanceStyle.computeDistance(planetModel, bottomPlane, x,y,z, topPlane, eitherBound);
+    // Because the rectangle exceeds 180 degrees, it is safe to compute the horizontally 
+    // unbounded distance to both the left and the right and only take the minimum of the two.
+    final double leftDistance = distanceStyle.computeDistance(planetModel, leftPlane, x,y,z, topPlane, bottomPlane);
+    final double rightDistance = distanceStyle.computeDistance(planetModel, rightPlane, x,y,z, topPlane, bottomPlane);
+    
+    final double ULHCDistance = distanceStyle.computeDistance(ULHC, x,y,z);
+    final double URHCDistance = distanceStyle.computeDistance(URHC, x,y,z);
+    final double LRHCDistance = distanceStyle.computeDistance(LRHC, x,y,z);
+    final double LLHCDistance = distanceStyle.computeDistance(LLHC, x,y,z);
+    
+    return Math.min(
+      Math.min(
+        Math.min(topDistance, bottomDistance),
+        Math.min(leftDistance, rightDistance)),
+      Math.min(
+        Math.min(ULHCDistance, URHCDistance),
+        Math.min(LRHCDistance, LLHCDistance)));
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof GeoWideRectangle))
+      return false;
+    GeoWideRectangle other = (GeoWideRectangle) o;
+    return super.equals(other) && other.ULHC.equals(ULHC) && other.LRHC.equals(LRHC);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + ULHC.hashCode();
+    result = 31 * result + LRHC.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoWideRectangle: {planetmodel=" + planetModel + ", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
+  }
+
+  /** A membership implementation representing a wide (more than 180) left/right bound.
+   */
+  protected class EitherBound implements Membership {
+    /** Constructor.
+      */
+    public EitherBound() {
+    }
+
+    @Override
+    public boolean isWithin(final Vector v) {
+      return leftPlane.isWithin(v) || rightPlane.isWithin(v);
+    }
+
+    @Override
+    public boolean isWithin(final double x, final double y, final double z) {
+      return leftPlane.isWithin(x, y, z) || rightPlane.isWithin(x, y, z);
+    }
+  }
+}
+  


[40/50] [abbrv] lucene-solr git commit: SOLR-6926: fix smokeTestRelease.py to stop calling ant example.

Posted by no...@apache.org.
SOLR-6926: fix smokeTestRelease.py to stop calling ant example.


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

Branch: refs/heads/apiv2
Commit: e490b329b3a6553720f3b422ce4422153baabad9
Parents: e3fcbfe
Author: David Smiley <ds...@apache.org>
Authored: Tue Mar 8 14:36:04 2016 -0500
Committer: David Smiley <ds...@apache.org>
Committed: Tue Mar 8 14:36:04 2016 -0500

----------------------------------------------------------------------
 dev-tools/scripts/smokeTestRelease.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e490b329/dev-tools/scripts/smokeTestRelease.py
----------------------------------------------------------------------
diff --git a/dev-tools/scripts/smokeTestRelease.py b/dev-tools/scripts/smokeTestRelease.py
index 87a772f..180599b 100644
--- a/dev-tools/scripts/smokeTestRelease.py
+++ b/dev-tools/scripts/smokeTestRelease.py
@@ -700,7 +700,7 @@ def verifyUnpacked(java, project, artifact, unpackPath, gitRevision, version, te
       checkJavadocpathFull('%s/solr/build/docs' % unpackPath, False)
 
       print('    test solr example w/ Java 8...')
-      java.run_java8('ant clean example', '%s/antexample.log' % unpackPath)
+      java.run_java8('ant clean server', '%s/antexample.log' % unpackPath)
       testSolrExample(unpackPath, java.java8_home, True)
 
       os.chdir('..')
@@ -782,6 +782,7 @@ def readSolrOutput(p, startupEvent, failureEvent, logFile):
     f.close()
     
 def testSolrExample(unpackPath, javaPath, isSrc):
+  # test solr using some examples it comes with
   logFile = '%s/solr-example.log' % unpackPath
   if isSrc:
     os.chdir(unpackPath+'/solr')


[41/50] [abbrv] lucene-solr git commit: SOLR-8793: Fix stale commit files' size computation in LukeRequestHandler

Posted by no...@apache.org.
SOLR-8793: Fix stale commit files' size computation in LukeRequestHandler


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

Branch: refs/heads/apiv2
Commit: 4384627f0891e4dc3232d3c7f20a54bc9224365c
Parents: e490b32
Author: Shai Erera <sh...@apache.org>
Authored: Tue Mar 8 22:11:18 2016 +0200
Committer: Shai Erera <sh...@apache.org>
Committed: Tue Mar 8 22:13:21 2016 +0200

----------------------------------------------------------------------
 solr/CHANGES.txt                                        |  5 +++++
 .../apache/solr/handler/admin/LukeRequestHandler.java   | 12 +++++++++++-
 2 files changed, 16 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4384627f/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index ecf8b32..d094b58 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -423,6 +423,11 @@ Bug Fixes
 * SOLR-8712: Variable solr.core.instanceDir was not being resolved (Kristine
   Jetzke, Shawn Heisey, Alan Woodward)
 
+* SOLR-8793: Fix Core admin status API to not fail when computing the size of the segments_N
+  file if the file no longer exists (for example, if a commit happened and the IndexReader
+  hasn't refreshed yet). In this case the reported size of the file is -1.
+  (Shai Erera, Alexey Serba, Richard Coggins)
+
 ======================= 5.5.0 =======================
 
 Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4384627f/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
index 0ec6d79..450a505 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
@@ -582,7 +582,7 @@ public class LukeRequestHandler extends RequestHandlerBase
     IndexCommit indexCommit = reader.getIndexCommit();
     String segmentsFileName = indexCommit.getSegmentsFileName();
     indexInfo.add("segmentsFile", segmentsFileName);
-    indexInfo.add("segmentsFileSizeInBytes", indexCommit.getDirectory().fileLength(segmentsFileName));
+    indexInfo.add("segmentsFileSizeInBytes", getFileLength(indexCommit.getDirectory(), segmentsFileName));
     Map<String,String> userData = indexCommit.getUserData();
     indexInfo.add("userData", userData);
     String s = userData.get(SolrIndexWriter.COMMIT_TIME_MSEC_KEY);
@@ -592,6 +592,16 @@ public class LukeRequestHandler extends RequestHandlerBase
     return indexInfo;
   }
 
+  private static long getFileLength(Directory dir, String filename) {
+    try {
+      return dir.fileLength(filename);
+    } catch (IOException e) {
+      // Whatever the error is, only log it and return -1.
+      log.warn("Error getting file length for [{}]", filename, e);
+      return -1;
+    }
+  }
+
   /** Returns the sum of RAM bytes used by each segment */
   private static long getIndexHeapUsed(DirectoryReader reader) {
     long indexHeapRamBytesUsed = 0;


[39/50] [abbrv] lucene-solr git commit: don't use slow composite reader in this test

Posted by no...@apache.org.
don't use slow composite reader in this test


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

Branch: refs/heads/apiv2
Commit: e3fcbfe7ce32b1286576bf6f08c93c3192987e41
Parents: 2cac33a
Author: Mike McCandless <mi...@apache.org>
Authored: Tue Mar 8 13:34:08 2016 -0500
Committer: Mike McCandless <mi...@apache.org>
Committed: Tue Mar 8 13:34:08 2016 -0500

----------------------------------------------------------------------
 .../apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e3fcbfe7/lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java
index a3e049d..80c3903 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java
@@ -480,7 +480,7 @@ public abstract class ThreadedIndexingAndSearchingTestCase extends LuceneTestCas
           }
         }
 
-        IndexSearcher searcher = newSearcher(reader);
+        IndexSearcher searcher = newSearcher(reader, false);
         sum += searcher.search(new TermQuery(new Term("body", "united")), 10).totalHits;
 
         if (VERBOSE) {


[04/50] [abbrv] lucene-solr git commit: SOLR-8736: schema GET operations on fields, dynamicFields, fieldTypes, copyField are reimplemented as a part of the bulk API with less details. The tests and write implementations are removed

Posted by no...@apache.org.
SOLR-8736: schema GET operations on fields, dynamicFields, fieldTypes, copyField are
  reimplemented as a part of the bulk API with less details. The tests and write implementations are removed


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

Branch: refs/heads/apiv2
Commit: f2c281abcbfc254d44c196ceb7c7f61311e7967c
Parents: 9082d5f
Author: Noble Paul <no...@apache.org>
Authored: Mon Mar 7 22:44:36 2016 +0530
Committer: Noble Paul <no...@apache.org>
Committed: Mon Mar 7 22:44:36 2016 +0530

----------------------------------------------------------------------
 solr/CHANGES.txt                                |   5 +
 .../org/apache/solr/handler/SchemaHandler.java  |  78 +++-
 .../org/apache/solr/rest/SolrSchemaRestApi.java |  56 +--
 .../solr/rest/schema/BaseFieldResource.java     | 146 --------
 .../solr/rest/schema/BaseFieldTypeResource.java |  98 -----
 .../schema/CopyFieldCollectionResource.java     | 198 ----------
 .../schema/DynamicFieldCollectionResource.java  | 207 -----------
 .../solr/rest/schema/DynamicFieldResource.java  | 197 ----------
 .../rest/schema/FieldCollectionResource.java    | 225 -----------
 .../apache/solr/rest/schema/FieldResource.java  | 201 ----------
 .../schema/FieldTypeCollectionResource.java     | 197 ----------
 .../solr/rest/schema/FieldTypeResource.java     | 203 ----------
 .../org/apache/solr/schema/IndexSchema.java     |  11 +-
 .../org/apache/solr/servlet/HttpSolrCall.java   |   3 +
 .../rest/schema/TestClassNameShortening.java    |   3 +-
 .../schema/TestCopyFieldCollectionResource.java |  96 +----
 .../TestDynamicFieldCollectionResource.java     |  29 --
 .../rest/schema/TestDynamicFieldResource.java   |   7 -
 .../schema/TestFieldCollectionResource.java     |  45 ---
 .../solr/rest/schema/TestFieldResource.java     |  23 +-
 .../schema/TestFieldTypeCollectionResource.java |   1 +
 .../solr/rest/schema/TestFieldTypeResource.java |  17 +-
 .../TestManagedSchemaDynamicFieldResource.java  | 366 ------------------
 .../schema/TestManagedSchemaFieldResource.java  | 369 -------------------
 .../TestManagedSchemaFieldTypeResource.java     | 350 ------------------
 .../schema/TestRemoveLastDynamicCopyField.java  |  80 ----
 .../schema/TestSchemaSimilarityResource.java    |   1 -
 .../analysis/TestManagedStopFilterFactory.java  |   2 +-
 .../TestManagedSynonymFilterFactory.java        |   6 +-
 .../TestCloudManagedSchemaConcurrent.java       |   3 +-
 .../solr/client/solrj/request/SchemaTest.java   |   4 -
 31 files changed, 125 insertions(+), 3102 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 61fcd47..7893b88 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -105,6 +105,8 @@ Upgrading from Solr 5.x
 
 * When requesting stats in date fields, "sum" is now a double value instead of a date. See SOLR-8671
 
+* SOLR-8736: The deprecated GET methods for schema are now accessible and implemented differently
+
 Detailed Change List
 ----------------------
 
@@ -395,6 +397,9 @@ Other Changes
 * SOLR-8758: Add a new SolrCloudTestCase class, using MiniSolrCloudCluster (Alan
   Woodward)
 
+* SOLR-8736: schema GET operations on fields, dynamicFields, fieldTypes, copyField are
+  reimplemented as a part of the bulk API with less details (noble)
+
 ==================  5.5.1 ==================
 
 Bug Fixes

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java b/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
index 046de46..4279864 100644
--- a/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
@@ -20,15 +20,20 @@ import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
 
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import org.apache.solr.cloud.ZkSolrResourceLoader;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.util.ContentStream;
-import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.common.util.StrUtils;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrRequestHandler;
@@ -42,17 +47,29 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static org.apache.solr.common.params.CommonParams.JSON;
-import static org.apache.solr.core.ConfigSetProperties.IMMUTABLE_CONFIGSET_ARG;
 
 public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
   private boolean isImmutableConfigSet = false;
 
-  @Override
-  public void init(NamedList args) {
-    super.init(args);
+  private static final Map<String, String> level2;
+
+  static {
+    Set<String> s = ImmutableSet.of(
+        IndexSchema.FIELD_TYPES,
+        IndexSchema.FIELDS,
+        IndexSchema.DYNAMIC_FIELDS,
+        IndexSchema.COPY_FIELDS
+    );
+    Map<String, String> m = new HashMap<>();
+    for (String s1 : s) {
+      m.put(s1, s1);
+      m.put(s1.toLowerCase(Locale.ROOT), s1);
+    }
+    level2 = ImmutableMap.copyOf(m);
   }
 
+
   @Override
   public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
     SolrConfigHandler.setWt(req, JSON);
@@ -150,6 +167,33 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware {
           break;
         }
         default: {
+          List<String> parts = StrUtils.splitSmart(path, '/');
+          if (parts.get(0).isEmpty()) parts.remove(0);
+          if (parts.size() > 1 && level2.containsKey(parts.get(1))) {
+            String realName = level2.get(parts.get(1));
+            SimpleOrderedMap<Object> propertyValues = req.getSchema().getNamedPropertyValues(req.getParams());
+            Object o = propertyValues.get(realName);
+            if(parts.size()> 2) {
+              String name = parts.get(2);
+              if (o instanceof List) {
+                List list = (List) o;
+                for (Object obj : list) {
+                  if (obj instanceof SimpleOrderedMap) {
+                    SimpleOrderedMap simpleOrderedMap = (SimpleOrderedMap) obj;
+                    if(name.equals(simpleOrderedMap.get("name"))) {
+                      rsp.add(realName.substring(0, realName.length() - 1), simpleOrderedMap);
+                      return;
+                    }
+                  }
+                }
+              }
+              throw new SolrException(SolrException.ErrorCode.NOT_FOUND, "No such path " + path);
+            } else {
+              rsp.add(realName, o);
+            }
+            return;
+          }
+
           throw new SolrException(SolrException.ErrorCode.NOT_FOUND, "No such path " + path);
         }
       }
@@ -160,19 +204,25 @@ public class SchemaHandler extends RequestHandlerBase implements SolrCoreAware {
   }
 
   private static Set<String> subPaths = new HashSet<>(Arrays.asList(
-      "/version",
-      "/uniquekey",
-      "/name",
-      "/similarity",
-      "/defaultsearchfield",
-      "/solrqueryparser",
-      "/zkversion",
-      "/solrqueryparser/defaultoperator"
+      "version",
+      "uniquekey",
+      "name",
+      "similarity",
+      "defaultsearchfield",
+      "solrqueryparser",
+      "zkversion"
   ));
+  static {
+    subPaths.addAll(level2.keySet());
+  }
 
   @Override
   public SolrRequestHandler getSubHandler(String subPath) {
-    if (subPaths.contains(subPath)) return this;
+    List<String> parts = StrUtils.splitSmart(subPath, '/');
+    if (parts.get(0).isEmpty()) parts.remove(0);
+    String prefix =  parts.get(0);
+    if(subPaths.contains(prefix)) return this;
+
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/java/org/apache/solr/rest/SolrSchemaRestApi.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/rest/SolrSchemaRestApi.java b/solr/core/src/java/org/apache/solr/rest/SolrSchemaRestApi.java
index 0e40f73..1310198 100644
--- a/solr/core/src/java/org/apache/solr/rest/SolrSchemaRestApi.java
+++ b/solr/core/src/java/org/apache/solr/rest/SolrSchemaRestApi.java
@@ -15,14 +15,14 @@
  * limitations under the License.
  */
 package org.apache.solr.rest;
+
+import java.lang.invoke.MethodHandles;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+
 import org.apache.solr.request.SolrRequestInfo;
-import org.apache.solr.rest.schema.CopyFieldCollectionResource;
-import org.apache.solr.rest.schema.DynamicFieldCollectionResource;
-import org.apache.solr.rest.schema.DynamicFieldResource;
-import org.apache.solr.rest.schema.FieldCollectionResource;
-import org.apache.solr.rest.schema.FieldResource;
-import org.apache.solr.rest.schema.FieldTypeCollectionResource;
-import org.apache.solr.rest.schema.FieldTypeResource;
 import org.apache.solr.schema.IndexSchema;
 import org.restlet.Application;
 import org.restlet.Restlet;
@@ -30,39 +30,18 @@ import org.restlet.routing.Router;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.lang.invoke.MethodHandles;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Set;
-
 /**
  * Restlet servlet handling /&lt;context&gt;/&lt;collection&gt;/schema/* URL paths
  */
 public class SolrSchemaRestApi extends Application {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-  public static final String FIELDS_PATH = "/" + IndexSchema.FIELDS;
-  
-  public static final String DYNAMIC_FIELDS = IndexSchema.DYNAMIC_FIELDS.toLowerCase(Locale.ROOT);
-  public static final String DYNAMIC_FIELDS_PATH = "/" + DYNAMIC_FIELDS;
-  
-  public static final String FIELDTYPES = IndexSchema.FIELD_TYPES.toLowerCase(Locale.ROOT);
-  public static final String FIELDTYPES_PATH = "/" + FIELDTYPES;
 
-  public static final String NAME_SEGMENT = "/{" + IndexSchema.NAME.toLowerCase(Locale.ROOT) + "}";
-  
-  public static final String COPY_FIELDS = IndexSchema.COPY_FIELDS.toLowerCase(Locale.ROOT);
-  public static final String COPY_FIELDS_PATH = "/" + COPY_FIELDS;
-  
+
   /**
    * Returns reserved endpoints under /schema
    */
   public static Set<String> getReservedEndpoints() {
     Set<String> reservedEndpoints = new HashSet<>();
-    reservedEndpoints.add(RestManager.SCHEMA_BASE_PATH + FIELDS_PATH);
-    reservedEndpoints.add(RestManager.SCHEMA_BASE_PATH + DYNAMIC_FIELDS_PATH);
-    reservedEndpoints.add(RestManager.SCHEMA_BASE_PATH + FIELDTYPES_PATH);
-    reservedEndpoints.add(RestManager.SCHEMA_BASE_PATH + COPY_FIELDS_PATH);
     return Collections.unmodifiableSet(reservedEndpoints);
   }
 
@@ -88,25 +67,6 @@ public class SolrSchemaRestApi extends Application {
     log.info("createInboundRoot started for /schema");
 
 
-    router.attach(FIELDS_PATH, FieldCollectionResource.class);
-    // Allow a trailing slash on collection requests
-    router.attach(FIELDS_PATH + "/", FieldCollectionResource.class);
-    router.attach(FIELDS_PATH + NAME_SEGMENT, FieldResource.class);
-
-    router.attach(DYNAMIC_FIELDS_PATH, DynamicFieldCollectionResource.class);
-    // Allow a trailing slash on collection requests
-    router.attach(DYNAMIC_FIELDS_PATH + "/", DynamicFieldCollectionResource.class);
-    router.attach(DYNAMIC_FIELDS_PATH + NAME_SEGMENT, DynamicFieldResource.class);
-
-    router.attach(FIELDTYPES_PATH, FieldTypeCollectionResource.class);
-    // Allow a trailing slash on collection requests
-    router.attach(FIELDTYPES_PATH + "/", FieldTypeCollectionResource.class);
-    router.attach(FIELDTYPES_PATH + NAME_SEGMENT, FieldTypeResource.class);
-
-    router.attach(COPY_FIELDS_PATH, CopyFieldCollectionResource.class);
-    // Allow a trailing slash on collection requests
-    router.attach(COPY_FIELDS_PATH + "/", CopyFieldCollectionResource.class);
-
     router.attachDefault(RestManager.ManagedEndpoint.class);
     
     // attach all the dynamically registered schema resources

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldResource.java b/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldResource.java
deleted file mode 100644
index 25f631d..0000000
--- a/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldResource.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * 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.
- */
-package org.apache.solr.rest.schema;
-import org.apache.solr.cloud.ZkSolrResourceLoader;
-import org.apache.solr.common.params.CommonParams;
-import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.solr.core.CoreDescriptor;
-import org.apache.solr.rest.BaseSolrResource;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.schema.ManagedIndexSchema;
-import org.apache.solr.schema.SchemaField;
-import org.restlet.resource.ResourceException;
-
-import java.util.LinkedHashSet;
-import java.util.Map;
-
-
-/**
- * Base class for Schema Field and DynamicField requests.
- */
-abstract class BaseFieldResource extends BaseSolrResource {
-  protected static final String INCLUDE_DYNAMIC_PARAM = "includeDynamic";
-  private static final String DYNAMIC_BASE = "dynamicBase";
-
-  private LinkedHashSet<String> requestedFields;
-  private boolean showDefaults;
-
-  protected LinkedHashSet<String> getRequestedFields() {
-    return requestedFields; 
-  }
-  
-
-  protected BaseFieldResource() {
-    super();
-  }
-
-  /**
-   * Pulls the "fl" param from the request and splits it to get the
-   * requested list of fields.  The (Dynamic)FieldCollectionResource classes
-   * will then restrict the fields sent back in the response to those
-   * on this list.  The (Dynamic)FieldResource classes ignore this list, 
-   * since the (dynamic) field is specified in the URL path, rather than
-   * in a query parameter.
-   * <p>
-   * Also pulls the "showDefaults" param from the request, for use by all
-   * subclasses to include default values from the associated field type
-   * in the response.  By default this param is off.
-   */
-  @Override
-  public void doInit() throws ResourceException {
-    super.doInit();
-    if (isExisting()) {
-      String flParam = getSolrRequest().getParams().get(CommonParams.FL);
-      if (null != flParam) {
-        String[] fields = flParam.trim().split("[,\\s]+");
-        if (fields.length > 0) {
-          requestedFields = new LinkedHashSet<>();
-          for (String field : fields) {
-            if ( ! field.trim().isEmpty()) {
-              requestedFields.add(field.trim());
-            }
-          }
-        }
-      }
-      showDefaults = getSolrRequest().getParams().getBool(SHOW_DEFAULTS, false);
-    }
-  }
-
-  /** Get the properties for a given field.
-   *
-   * @param field not required to exist in the schema
-   */
-  protected SimpleOrderedMap<Object> getFieldProperties(SchemaField field) {
-    if (null == field) {
-      return null;
-    }
-    SimpleOrderedMap<Object> properties = field.getNamedPropertyValues(showDefaults);
-    if ( ! getSchema().getFields().containsKey(field.getName())) {
-      String dynamicBase = getSchema().getDynamicPattern(field.getName());
-      // Add dynamicBase property if it's different from the field name. 
-      if ( ! field.getName().equals(dynamicBase)) {
-        properties.add(DYNAMIC_BASE, dynamicBase);
-      }
-    }
-    if (field == getSchema().getUniqueKeyField()) {
-      properties.add(IndexSchema.UNIQUE_KEY, true);
-    }
-    return properties;
-  }
-
-  /**
-   * When running in cloud mode, waits for a schema update to be
-   * applied by all active replicas of the current collection.
-   */
-  protected void waitForSchemaUpdateToPropagate(IndexSchema newSchema) {
-    // If using ZooKeeper and the client application has requested an update timeout, then block until all
-    // active replicas for this collection process the updated schema
-    if (getUpdateTimeoutSecs() > 0 && newSchema != null &&
-        newSchema.getResourceLoader() instanceof ZkSolrResourceLoader)
-    {
-      CoreDescriptor cd = getSolrCore().getCoreDescriptor();
-      String collection = cd.getCollectionName();
-      if (collection != null) {
-        ZkSolrResourceLoader zkLoader = (ZkSolrResourceLoader) newSchema.getResourceLoader();
-        ManagedIndexSchema.waitForSchemaZkVersionAgreement(collection,
-            cd.getCloudDescriptor().getCoreNodeName(),
-            ((ManagedIndexSchema) newSchema).getSchemaZkVersion(),
-            zkLoader.getZkController(),
-            getUpdateTimeoutSecs());
-      }
-    }
-  }
-
-  // protected access on this class triggers a bug in javadoc generation caught by
-  // documentation-link: "BROKEN LINK" reported in javadoc for classes using
-  // NewFieldArguments because the link target file is BaseFieldResource.NewFieldArguments,
-  // but the actual file is BaseFieldResource$NewFieldArguments.
-  static class NewFieldArguments {
-    private String name;
-    private String type;
-    Map<String,Object> map;
-    NewFieldArguments(String name, String type, Map<String,Object> map) {
-      this.name = name;
-      this.type = type;
-      this.map = map;
-    }
-
-    public String getName() { return name; }
-    public String getType() { return type; }
-    public Map<String, Object> getMap() { return map; }
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java b/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java
deleted file mode 100644
index c475dd0..0000000
--- a/solr/core/src/java/org/apache/solr/rest/schema/BaseFieldTypeResource.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.
- */
-package org.apache.solr.rest.schema;
-
-import org.apache.solr.cloud.ZkSolrResourceLoader;
-import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.solr.core.CoreDescriptor;
-import org.apache.solr.rest.BaseSolrResource;
-import org.apache.solr.schema.FieldType;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.schema.ManagedIndexSchema;
-import org.restlet.resource.ResourceException;
-
-import java.util.List;
-
-/**
- * Base class for the FieldType resource classes.
- */
-abstract class BaseFieldTypeResource extends BaseSolrResource {
-  private boolean showDefaults;
-
-  protected BaseFieldTypeResource() {
-    super();
-  }
-
-  @Override
-  public void doInit() throws ResourceException {
-    super.doInit();
-    if (isExisting()) {
-      showDefaults = getSolrRequest().getParams().getBool(SHOW_DEFAULTS, false);
-    }
-  }
-  
-  /** Used by subclasses to collect field type properties */
-  protected SimpleOrderedMap<Object> getFieldTypeProperties(FieldType fieldType) {
-    SimpleOrderedMap<Object> properties = fieldType.getNamedPropertyValues(showDefaults);
-    properties.add(IndexSchema.FIELDS, getFieldsWithFieldType(fieldType));
-    properties.add(IndexSchema.DYNAMIC_FIELDS, getDynamicFieldsWithFieldType(fieldType));
-    return properties;
-  }
-
-  
-  /** Return a list of names of Fields that have the given FieldType */
-  protected abstract List<String> getFieldsWithFieldType(FieldType fieldType);
-
-  /** Return a list of names of DynamicFields that have the given FieldType */
-  protected abstract List<String> getDynamicFieldsWithFieldType(FieldType fieldType);
-
-  /**
-   * Adds one or more new FieldType definitions to the managed schema for the given core.
-   */
-  protected void addNewFieldTypes(List<FieldType> newFieldTypes, ManagedIndexSchema oldSchema) {
-    IndexSchema newSchema = null;
-    boolean success = false;
-    while (!success) {
-      try {
-        synchronized (oldSchema.getSchemaUpdateLock()) {
-          newSchema = oldSchema.addFieldTypes(newFieldTypes, true);
-          getSolrCore().setLatestSchema(newSchema);
-          success = true;
-        }
-      } catch (ManagedIndexSchema.SchemaChangedInZkException e) {
-        oldSchema = (ManagedIndexSchema)getSolrCore().getLatestSchema();
-      }
-    }
-
-    // If using ZooKeeper and the client application has requested an update timeout, then block until all
-    // active replicas for this collection process the updated schema
-    if (getUpdateTimeoutSecs() > 0 && newSchema != null &&
-        newSchema.getResourceLoader() instanceof ZkSolrResourceLoader)
-    {
-      CoreDescriptor cd = getSolrCore().getCoreDescriptor();
-      String collection = cd.getCollectionName();
-      if (collection != null) {
-        ZkSolrResourceLoader zkLoader = (ZkSolrResourceLoader) newSchema.getResourceLoader();
-        ManagedIndexSchema.waitForSchemaZkVersionAgreement(collection,
-            cd.getCloudDescriptor().getCoreNodeName(),
-            ((ManagedIndexSchema) newSchema).getSchemaZkVersion(),
-            zkLoader.getZkController(),
-            getUpdateTimeoutSecs());
-      }
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/java/org/apache/solr/rest/schema/CopyFieldCollectionResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/rest/schema/CopyFieldCollectionResource.java b/solr/core/src/java/org/apache/solr/rest/schema/CopyFieldCollectionResource.java
deleted file mode 100644
index 610c054..0000000
--- a/solr/core/src/java/org/apache/solr/rest/schema/CopyFieldCollectionResource.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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.
- */
-package org.apache.solr.rest.schema;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.params.CommonParams;
-import org.apache.solr.rest.GETable;
-import org.apache.solr.rest.POSTable;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.schema.ManagedIndexSchema;
-import org.noggit.ObjectBuilder;
-import org.restlet.data.MediaType;
-import org.restlet.representation.Representation;
-import org.restlet.resource.ResourceException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.lang.invoke.MethodHandles;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.apache.solr.common.SolrException.ErrorCode;
-
-/**
- * This class responds to requests at /solr/(corename)/schema/copyfields
- * <p>
- *
- * To restrict the set of copyFields in the response, specify one or both
- * of the following as query parameters, with values as space and/or comma
- * separated dynamic or explicit field names:
- *
- * <ul>
- *   <li>dest.fl: include copyFields that have one of these as a destination</li>
- *   <li>source.fl: include copyFields that have one of these as a source</li>
- * </ul>
- *
- * If both dest.fl and source.fl are given as query parameters, the copyfields
- * in the response will be restricted to those that match any of the destinations
- * in dest.fl and also match any of the sources in source.fl.
- */
-public class CopyFieldCollectionResource extends BaseFieldResource implements GETable, POSTable {
-  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-  private static final String SOURCE_FIELD_LIST = IndexSchema.SOURCE + "." + CommonParams.FL;
-  private static final String DESTINATION_FIELD_LIST = IndexSchema.DESTINATION + "." + CommonParams.FL;
-
-  private Set<String> requestedSourceFields;
-  private Set<String> requestedDestinationFields;
-
-  public CopyFieldCollectionResource() {
-    super();
-  }
-
-  @Override
-  public void doInit() throws ResourceException {
-    super.doInit();
-    if (isExisting()) {
-      String sourceFieldListParam = getSolrRequest().getParams().get(SOURCE_FIELD_LIST);
-      if (null != sourceFieldListParam) {
-        String[] fields = sourceFieldListParam.trim().split("[,\\s]+");
-        if (fields.length > 0) {
-          requestedSourceFields = new HashSet<>(Arrays.asList(fields));
-          requestedSourceFields.remove(""); // Remove empty values, if any
-        }
-      }
-      String destinationFieldListParam = getSolrRequest().getParams().get(DESTINATION_FIELD_LIST);
-      if (null != destinationFieldListParam) {
-        String[] fields = destinationFieldListParam.trim().split("[,\\s]+");
-        if (fields.length > 0) {
-          requestedDestinationFields = new HashSet<>(Arrays.asList(fields));
-          requestedDestinationFields.remove(""); // Remove empty values, if any
-        }
-      }
-    }
-  }
-
-  @Override
-  public Representation get() {
-    try {
-      getSolrResponse().add(IndexSchema.COPY_FIELDS,
-          getSchema().getCopyFieldProperties(true, requestedSourceFields, requestedDestinationFields));
-    } catch (Exception e) {
-      getSolrResponse().setException(e);
-    }
-    handlePostExecution(log);
-
-    return new SolrOutputRepresentation();
-  }
-
-  @Override
-  public Representation post(Representation entity) throws ResourceException {
-    try {
-      if (!getSchema().isMutable()) {
-        final String message = "This IndexSchema is not mutable.";
-        throw new SolrException(ErrorCode.BAD_REQUEST, message);
-      } else {
-        if (!entity.getMediaType().equals(MediaType.APPLICATION_JSON, true)) {
-          String message = "Only media type " + MediaType.APPLICATION_JSON.toString() + " is accepted."
-              + "  Request has media type " + entity.getMediaType().toString() + ".";
-          log.error(message);
-          throw new SolrException(ErrorCode.BAD_REQUEST, message);
-        } else {
-          Object object = ObjectBuilder.fromJSON(entity.getText());
-
-          if (!(object instanceof List)) {
-            String message = "Invalid JSON type " + object.getClass().getName() + ", expected List of the form"
-                + " (ignore the backslashes): [{\"source\":\"foo\",\"dest\":\"comma-separated list of targets\"}, {...}, ...]";
-            log.error(message);
-            throw new SolrException(ErrorCode.BAD_REQUEST, message);
-          } else {
-            List<Map<String, Object>> list = (List<Map<String, Object>>) object;
-            Map<String, Collection<String>> fieldsToCopy = new HashMap<>();
-            ManagedIndexSchema oldSchema = (ManagedIndexSchema) getSchema();
-            Set<String> malformed = new HashSet<>();
-            for (Map<String,Object> map : list) {
-              String fieldName = (String)map.get(IndexSchema.SOURCE);
-              if (null == fieldName) {
-                String message = "Missing '" + IndexSchema.SOURCE + "' mapping.";
-                log.error(message);
-                throw new SolrException(ErrorCode.BAD_REQUEST, message);
-              }
-              Object dest = map.get(IndexSchema.DESTINATION);
-              List<String> destinations = null;
-              if (dest != null) {
-                if (dest instanceof List){
-                  destinations = (List<String>)dest;
-                } else if (dest instanceof String){
-                  destinations = Collections.singletonList(dest.toString());
-                } else {
-                  String message = "Invalid '" + IndexSchema.DESTINATION + "' type.";
-                  log.error(message);
-                  throw new SolrException(ErrorCode.BAD_REQUEST, message);
-                }
-              }
-              if (destinations == null) {
-                malformed.add(fieldName);
-              } else {
-                fieldsToCopy.put(fieldName, destinations);
-              }
-            }
-            if (malformed.size() > 0){
-              StringBuilder message = new StringBuilder("Malformed destination(s) for: ");
-              for (String s : malformed) {
-                message.append(s).append(", ");
-              }
-              if (message.length() > 2) {
-                message.setLength(message.length() - 2);//drop the last ,
-              }
-              log.error(message.toString().trim());
-              throw new SolrException(ErrorCode.BAD_REQUEST, message.toString().trim());
-            }
-            IndexSchema newSchema = null;
-            boolean success = false;
-            while (!success) {
-              try {
-                synchronized (oldSchema.getSchemaUpdateLock()) {
-                  newSchema = oldSchema.addCopyFields(fieldsToCopy,true);
-                  if (null != newSchema) {
-                    getSolrCore().setLatestSchema(newSchema);
-                    success = true;
-                  } else {
-                    throw new SolrException(ErrorCode.SERVER_ERROR, "Failed to add fields.");
-                  }
-                }
-              } catch (ManagedIndexSchema.SchemaChangedInZkException e) {
-                  log.debug("Schema changed while processing request, retrying");
-                  oldSchema = (ManagedIndexSchema)getSolrCore().getLatestSchema();
-              }
-            }
-            waitForSchemaUpdateToPropagate(newSchema);
-          }
-        }
-      }
-    } catch (Exception e) {
-      getSolrResponse().setException(e);
-    }
-    handlePostExecution(log);
-    return new SolrOutputRepresentation();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldCollectionResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldCollectionResource.java b/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldCollectionResource.java
deleted file mode 100644
index bf94234..0000000
--- a/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldCollectionResource.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * 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.
- */
-package org.apache.solr.rest.schema;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.common.params.CommonParams;
-import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.solr.rest.GETable;
-import org.apache.solr.rest.POSTable;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.schema.ManagedIndexSchema;
-import org.apache.solr.schema.SchemaField;
-import org.noggit.ObjectBuilder;
-import org.restlet.data.MediaType;
-import org.restlet.representation.Representation;
-import org.restlet.resource.ResourceException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * This class responds to requests at /solr/(corename)/schema/dynamicfields
- * <p>
- * To restrict the set of dynamic fields in the response, specify a comma
- * and/or space separated list of dynamic field patterns in the "fl" query
- * parameter. 
- */
-public class DynamicFieldCollectionResource extends BaseFieldResource implements GETable, POSTable {
-  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
-  public DynamicFieldCollectionResource() {
-    super();
-  }
-
-  @Override
-  public void doInit() throws ResourceException {
-    super.doInit();
-  }
-
-  @Override
-  public Representation get() {
-    
-    try {
-      List<SimpleOrderedMap<Object>> props = new ArrayList<>();
-      if (null == getRequestedFields()) {
-        for (IndexSchema.DynamicField dynamicField : getSchema().getDynamicFields()) {
-          if ( ! dynamicField.getRegex().startsWith(IndexSchema.INTERNAL_POLY_FIELD_PREFIX)) { // omit internal polyfields
-            props.add(getFieldProperties(dynamicField.getPrototype()));
-          }
-        }
-      } else {
-        if (0 == getRequestedFields().size()) {
-          String message = "Empty " + CommonParams.FL + " parameter value";
-          throw new SolrException(ErrorCode.BAD_REQUEST, message);
-        }
-        Map<String,SchemaField> dynamicFieldsByName = new HashMap<>();
-        for (IndexSchema.DynamicField dynamicField : getSchema().getDynamicFields()) {
-          dynamicFieldsByName.put(dynamicField.getRegex(), dynamicField.getPrototype());
-        }
-        // Use the same order as the fl parameter
-        for (String dynamicFieldName : getRequestedFields()) {
-          final SchemaField dynamicSchemaField = dynamicFieldsByName.get(dynamicFieldName);
-          if (null == dynamicSchemaField) {
-            log.info("Requested dynamic field '" + dynamicFieldName + "' not found.");
-          } else {
-            props.add(getFieldProperties(dynamicSchemaField));
-          }
-        }
-      }
-      getSolrResponse().add(IndexSchema.DYNAMIC_FIELDS, props);
-    } catch (Exception e) {
-      getSolrResponse().setException(e);
-    }
-    handlePostExecution(log);
-
-    return new SolrOutputRepresentation();
-  }
-
-  @Override
-  public Representation post(Representation entity) {
-    try {
-      if ( ! getSchema().isMutable()) {
-        final String message = "This IndexSchema is not mutable.";
-        throw new SolrException(ErrorCode.BAD_REQUEST, message);
-      } else {
-        if (null == entity.getMediaType()) {
-          entity.setMediaType(MediaType.APPLICATION_JSON);
-        }
-        if ( ! entity.getMediaType().equals(MediaType.APPLICATION_JSON, true)) {
-          String message = "Only media type " + MediaType.APPLICATION_JSON.toString() + " is accepted."
-              + "  Request has media type " + entity.getMediaType().toString() + ".";
-          log.error(message);
-          throw new SolrException(ErrorCode.BAD_REQUEST, message);
-        } else {
-          Object object = ObjectBuilder.fromJSON(entity.getText());
-          if ( ! (object instanceof List)) {
-            String message = "Invalid JSON type " + object.getClass().getName() + ", expected List of the form"
-                + " (ignore the backslashes): [{\"name\":\"*_foo\",\"type\":\"text_general\", ...}, {...}, ...]";
-            log.error(message);
-            throw new SolrException(ErrorCode.BAD_REQUEST, message);
-          } else {
-            List<Map<String,Object>> list = (List<Map<String,Object>>)object;
-            List<SchemaField> newDynamicFields = new ArrayList<>();
-            List<NewFieldArguments> newDynamicFieldArguments = new ArrayList<>();
-            ManagedIndexSchema oldSchema = (ManagedIndexSchema)getSchema();
-            Map<String,Collection<String>> copyFields = new HashMap<>();
-            for (Map<String,Object> map : list) {
-              String fieldNamePattern = (String)map.remove(IndexSchema.NAME);
-              if (null == fieldNamePattern) {
-                String message = "Missing '" + IndexSchema.NAME + "' mapping.";
-                log.error(message);
-                throw new SolrException(ErrorCode.BAD_REQUEST, message);
-              }
-              String fieldType = (String)map.remove(IndexSchema.TYPE);
-              if (null == fieldType) {
-                String message = "Missing '" + IndexSchema.TYPE + "' mapping.";
-                log.error(message);
-                throw new SolrException(ErrorCode.BAD_REQUEST, message);
-              }
-              // copyFields:"comma separated list of destination fields"
-              Object copies = map.get(IndexSchema.COPY_FIELDS);
-              List<String> copyTo = null;
-              if (copies != null) {
-                if (copies instanceof List){
-                  copyTo = (List<String>)copies;
-                } else if (copies instanceof String){
-                  copyTo = Collections.singletonList(copies.toString());
-                } else {
-                  String message = "Invalid '" + IndexSchema.COPY_FIELDS + "' type.";
-                  log.error(message);
-                  throw new SolrException(ErrorCode.BAD_REQUEST, message);
-                }
-              }
-              if (copyTo != null) {
-                map.remove(IndexSchema.COPY_FIELDS);
-                copyFields.put(fieldNamePattern, copyTo);
-              }
-              newDynamicFields.add(oldSchema.newDynamicField(fieldNamePattern, fieldType, map));
-              newDynamicFieldArguments.add(new NewFieldArguments(fieldNamePattern, fieldType, map));
-            }
-            IndexSchema newSchema = null;
-            boolean firstAttempt = true;
-            boolean success = false;
-            while ( ! success) {
-              try {
-                if ( ! firstAttempt) {
-                  // If this isn't the first attempt, we must have failed due to
-                  // the schema changing in Zk during optimistic concurrency control.
-                  // In that case, rerun creating the new fields, because they may
-                  // fail now due to changes in the schema.  This behavior is consistent
-                  // with what would happen if we locked the schema and the other schema
-                  // change went first.
-                  newDynamicFields.clear();
-                  for (NewFieldArguments args : newDynamicFieldArguments) {
-                    newDynamicFields.add(oldSchema.newDynamicField(args.getName(), args.getType(), args.getMap()));
-                  }
-                }
-                firstAttempt = false;
-                synchronized (oldSchema.getSchemaUpdateLock()) {
-                  newSchema = oldSchema.addDynamicFields(newDynamicFields, copyFields, true);
-                  if (null != newSchema) {
-                    getSolrCore().setLatestSchema(newSchema);
-                    success = true;
-                  } else {
-                    throw new SolrException(ErrorCode.SERVER_ERROR, "Failed to add dynamic fields.");
-                  }
-                }
-              } catch (ManagedIndexSchema.SchemaChangedInZkException e) {
-                log.debug("Schema changed while processing request, retrying");
-                oldSchema = (ManagedIndexSchema)getSolrCore().getLatestSchema();
-              }
-            }
-
-            waitForSchemaUpdateToPropagate(newSchema);
-
-          }
-        }
-      }
-    } catch (Exception e) {
-      getSolrResponse().setException(e);
-    }
-    handlePostExecution(log);
-
-    return new SolrOutputRepresentation();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldResource.java b/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldResource.java
deleted file mode 100644
index bf67608..0000000
--- a/solr/core/src/java/org/apache/solr/rest/schema/DynamicFieldResource.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * 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.
- */
-package org.apache.solr.rest.schema;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.rest.GETable;
-import org.apache.solr.rest.PUTable;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.schema.ManagedIndexSchema;
-import org.apache.solr.schema.SchemaField;
-import org.noggit.ObjectBuilder;
-import org.restlet.data.MediaType;
-import org.restlet.representation.Representation;
-import org.restlet.resource.ResourceException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.UnsupportedEncodingException;
-import java.lang.invoke.MethodHandles;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static java.util.Collections.singletonList;
-import static java.util.Collections.singletonMap;
-
-/**
- * This class responds to requests at /solr/(corename)/schema/dynamicfields/(pattern)
- * where pattern is a field name pattern (with an asterisk at the beginning or the end).
- */
-public class DynamicFieldResource extends BaseFieldResource implements GETable, PUTable {
-  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
-  private String fieldNamePattern;
-
-  public DynamicFieldResource() {
-    super();
-  }
-
-  /**
-   * Gets the field name pattern from the request attribute where it's stored by Restlet. 
-   */
-  @Override
-  public void doInit() throws ResourceException {
-    super.doInit();
-    if (isExisting()) {
-      fieldNamePattern = (String)getRequestAttributes().get(IndexSchema.NAME);
-      try {
-        fieldNamePattern = null == fieldNamePattern ? "" : urlDecode(fieldNamePattern.trim()).trim();
-      } catch (UnsupportedEncodingException e) {
-        throw new ResourceException(e);
-      }
-    }
-  }
-
-  @Override
-  public Representation get() {
-    try {
-      if (fieldNamePattern.isEmpty()) {
-        final String message = "Dynamic field name is missing";
-        throw new SolrException(ErrorCode.BAD_REQUEST, message);
-      } else {
-        SchemaField field = null;
-        for (SchemaField prototype : getSchema().getDynamicFieldPrototypes()) {
-          if (prototype.getName().equals(fieldNamePattern)) {
-            field = prototype;
-            break;
-          }
-        }
-        if (null == field) {
-          final String message = "Dynamic field '" + fieldNamePattern + "' not found.";
-          throw new SolrException(ErrorCode.NOT_FOUND, message);
-        } else {
-          getSolrResponse().add(IndexSchema.DYNAMIC_FIELD, getFieldProperties(field));
-        }
-      }
-    } catch (Exception e) {
-      getSolrResponse().setException(e);
-    }
-    handlePostExecution(log);
-
-    return new SolrOutputRepresentation();
-  }
-
-  /**
-   * Accepts JSON add dynamic field request
-   */
-  @Override
-  public Representation put(Representation entity) {
-    try {
-      if ( ! getSchema().isMutable()) {
-        final String message = "This IndexSchema is not mutable.";
-        throw new SolrException(ErrorCode.BAD_REQUEST, message);
-      } else {
-        if (null == entity.getMediaType()) {
-          entity.setMediaType(MediaType.APPLICATION_JSON);
-        }
-        if ( ! entity.getMediaType().equals(MediaType.APPLICATION_JSON, true)) {
-          String message = "Only media type " + MediaType.APPLICATION_JSON.toString() + " is accepted."
-                         + "  Request has media type " + entity.getMediaType().toString() + ".";
-          log.error(message);
-          throw new SolrException(ErrorCode.BAD_REQUEST, message);
-        } else {
-          Object object = ObjectBuilder.fromJSON(entity.getText());
-          if ( ! (object instanceof Map)) {
-            String message = "Invalid JSON type " + object.getClass().getName() + ", expected Map of the form"
-                           + " (ignore the backslashes): {\"type\":\"text_general\", ...}, either with or"
-                           + " without a \"name\" mapping.  If the \"name\" is specified, it must match the"
-                           + " name given in the request URL: /schema/dynamicfields/(name)";
-            log.error(message);
-            throw new SolrException(ErrorCode.BAD_REQUEST, message);
-          } else {
-            Map<String,Object> map = (Map<String,Object>)object;
-            if (1 == map.size() && map.containsKey(IndexSchema.DYNAMIC_FIELD)) {
-              map = (Map<String,Object>)map.get(IndexSchema.DYNAMIC_FIELD);
-            }
-            String bodyFieldName;
-            if (null != (bodyFieldName = (String)map.remove(IndexSchema.NAME))
-                && ! fieldNamePattern.equals(bodyFieldName)) {
-              String message = "Dynamic field name in the request body '" + bodyFieldName
-                  + "' doesn't match dynamic field name in the request URL '" + fieldNamePattern + "'";
-              log.error(message);
-              throw new SolrException(ErrorCode.BAD_REQUEST, message);
-            } else {
-              String fieldType;
-              if (null == (fieldType = (String) map.remove(IndexSchema.TYPE))) {
-                String message = "Missing '" + IndexSchema.TYPE + "' mapping.";
-                log.error(message);
-                throw new SolrException(ErrorCode.BAD_REQUEST, message);
-              } else {
-                ManagedIndexSchema oldSchema = (ManagedIndexSchema)getSchema();
-                Object copies = map.get(IndexSchema.COPY_FIELDS);
-                Collection<String> copyFieldNames = null;
-                if (copies != null) {
-                  if (copies instanceof List) {
-                    copyFieldNames = (List<String>)copies;
-                  } else if (copies instanceof String) {
-                    copyFieldNames = singletonList(copies.toString());
-                  } else {
-                    String message = "Invalid '" + IndexSchema.COPY_FIELDS + "' type.";
-                    log.error(message);
-                    throw new SolrException(ErrorCode.BAD_REQUEST, message);
-                  }
-                }
-                if (copyFieldNames != null) {
-                  map.remove(IndexSchema.COPY_FIELDS);
-                }
-                IndexSchema newSchema = null;
-                boolean success = false;
-                while ( ! success) {
-                  try {
-                    SchemaField newDynamicField = oldSchema.newDynamicField(fieldNamePattern, fieldType, map);
-                    synchronized (oldSchema.getSchemaUpdateLock()) {
-                      newSchema = oldSchema.addDynamicFields(singletonList(newDynamicField), singletonMap(newDynamicField.getName(), copyFieldNames), true);
-                      if (null != newSchema) {
-                        getSolrCore().setLatestSchema(newSchema);
-                        success = true;
-                      } else {
-                        throw new SolrException(ErrorCode.SERVER_ERROR, "Failed to add dynamic field.");
-                      }
-                    }
-                  } catch (ManagedIndexSchema.SchemaChangedInZkException e) {
-                    log.debug("Schema changed while processing request, retrying");
-                    oldSchema = (ManagedIndexSchema)getSolrCore().getLatestSchema();
-                  }
-                }
-                // if in cloud mode, wait for schema updates to propagate to all replicas
-                waitForSchemaUpdateToPropagate(newSchema);
-              }
-            }
-          }
-        }
-      }
-    } catch (Exception e) {
-      getSolrResponse().setException(e);
-    }
-    handlePostExecution(log);
-
-    return new SolrOutputRepresentation();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/java/org/apache/solr/rest/schema/FieldCollectionResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/rest/schema/FieldCollectionResource.java b/solr/core/src/java/org/apache/solr/rest/schema/FieldCollectionResource.java
deleted file mode 100644
index f1bf6a4..0000000
--- a/solr/core/src/java/org/apache/solr/rest/schema/FieldCollectionResource.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * 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.
- */
-package org.apache.solr.rest.schema;
-import org.apache.solr.cloud.ZkSolrResourceLoader;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.common.params.CommonParams;
-import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.solr.core.CoreDescriptor;
-import org.apache.solr.rest.GETable;
-import org.apache.solr.rest.POSTable;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.schema.ManagedIndexSchema;
-import org.apache.solr.schema.SchemaField;
-import org.noggit.ObjectBuilder;
-import org.restlet.data.MediaType;
-import org.restlet.representation.Representation;
-import org.restlet.resource.ResourceException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-/**
- * This class responds to requests at /solr/(corename)/schema/fields
- * <p>
- * Two query parameters are supported:
- * <ul>
- * <li>
- * "fl": a comma- and/or space-separated list of fields to send properties
- * for in the response, rather than the default: all of them.
- * </li>
- * <li>
- * "includeDynamic": if the "fl" parameter is specified, matching dynamic
- * fields are included in the response and identified with the "dynamicBase"
- * property.  If the "fl" parameter is not specified, the "includeDynamic"
- * query parameter is ignored.
- * </li>
- * </ul>
- */
-public class FieldCollectionResource extends BaseFieldResource implements GETable, POSTable {
-  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-  private boolean includeDynamic;
-
-  public FieldCollectionResource() {
-    super();
-  }
-
-  @Override
-  public void doInit() throws ResourceException {
-    super.doInit();
-    if (isExisting()) {
-      includeDynamic = getSolrRequest().getParams().getBool(INCLUDE_DYNAMIC_PARAM, false);
-    }
-  }
-
-  @Override
-  public Representation get() {
-    try {
-      final List<SimpleOrderedMap<Object>> props = new ArrayList<>();
-      if (null == getRequestedFields()) {
-        SortedSet<String> fieldNames = new TreeSet<>(getSchema().getFields().keySet());
-        for (String fieldName : fieldNames) {
-          props.add(getFieldProperties(getSchema().getFields().get(fieldName)));
-        }
-      } else {
-        if (0 == getRequestedFields().size()) {
-          String message = "Empty " + CommonParams.FL + " parameter value";
-          throw new SolrException(ErrorCode.BAD_REQUEST, message);
-        }
-        // Use the same order as the fl parameter
-        for (String fieldName : getRequestedFields()) {
-          final SchemaField field;
-          if (includeDynamic) {
-            field = getSchema().getFieldOrNull(fieldName);
-          } else {
-            field = getSchema().getFields().get(fieldName);
-          }
-          if (null == field) {
-            log.info("Requested field '" + fieldName + "' not found.");
-          } else {
-            props.add(getFieldProperties(field));
-          }
-        }
-      }
-      getSolrResponse().add(IndexSchema.FIELDS, props);
-    } catch (Exception e) {
-      getSolrResponse().setException(e);
-    }
-    handlePostExecution(log);
-
-    return new SolrOutputRepresentation();
-  }
-
-  @Override
-  public Representation post(Representation entity) {
-    try {
-      if (!getSchema().isMutable()) {
-        final String message = "This IndexSchema is not mutable.";
-        throw new SolrException(ErrorCode.BAD_REQUEST, message);
-      } else {
-        if (null == entity.getMediaType()) {
-          entity.setMediaType(MediaType.APPLICATION_JSON);
-        }
-        if (!entity.getMediaType().equals(MediaType.APPLICATION_JSON, true)) {
-          String message = "Only media type " + MediaType.APPLICATION_JSON.toString() + " is accepted."
-              + "  Request has media type " + entity.getMediaType().toString() + ".";
-          log.error(message);
-          throw new SolrException(ErrorCode.BAD_REQUEST, message);
-        } else {
-          Object object = ObjectBuilder.fromJSON(entity.getText());
-          if (!(object instanceof List)) {
-            String message = "Invalid JSON type " + object.getClass().getName() + ", expected List of the form"
-                + " (ignore the backslashes): [{\"name\":\"foo\",\"type\":\"text_general\", ...}, {...}, ...]";
-            log.error(message);
-            throw new SolrException(ErrorCode.BAD_REQUEST, message);
-          } else {
-            List<Map<String, Object>> list = (List<Map<String, Object>>) object;
-            List<SchemaField> newFields = new ArrayList<>();
-            List<NewFieldArguments> newFieldArguments = new ArrayList<>();
-            IndexSchema oldSchema = getSchema();
-            Map<String, Collection<String>> copyFields = new HashMap<>();
-            for (Map<String, Object> map : list) {
-              String fieldName = (String) map.remove(IndexSchema.NAME);
-              if (null == fieldName) {
-                String message = "Missing '" + IndexSchema.NAME + "' mapping.";
-                log.error(message);
-                throw new SolrException(ErrorCode.BAD_REQUEST, message);
-              }
-              String fieldType = (String) map.remove(IndexSchema.TYPE);
-              if (null == fieldType) {
-                String message = "Missing '" + IndexSchema.TYPE + "' mapping.";
-                log.error(message);
-                throw new SolrException(ErrorCode.BAD_REQUEST, message);
-              }
-              // copyFields:"comma separated list of destination fields"
-              Object copies = map.get(IndexSchema.COPY_FIELDS);
-              List<String> copyTo = null;
-              if (copies != null) {
-                if (copies instanceof List){
-                  copyTo = (List<String>) copies;
-                } else if (copies instanceof String){
-                  copyTo = Collections.singletonList(copies.toString());
-                } else {
-                  String message = "Invalid '" + IndexSchema.COPY_FIELDS + "' type.";
-                  log.error(message);
-                  throw new SolrException(ErrorCode.BAD_REQUEST, message);
-                }
-              }
-              if (copyTo != null) {
-                map.remove(IndexSchema.COPY_FIELDS);
-                copyFields.put(fieldName, copyTo);
-              }
-              newFields.add(oldSchema.newField(fieldName, fieldType, map));
-              newFieldArguments.add(new NewFieldArguments(fieldName, fieldType, map));
-            }
-            IndexSchema newSchema = null;
-            boolean firstAttempt = true;
-            boolean success = false;
-            while (!success) {
-              try {
-                if (!firstAttempt) {
-                  // If this isn't the first attempt, we must have failed due to
-                  // the schema changing in Zk during optimistic concurrency control.
-                  // In that case, rerun creating the new fields, because they may
-                  // fail now due to changes in the schema.  This behavior is consistent
-                  // with what would happen if we locked the schema and the other schema
-                  // change went first.
-                  newFields.clear();
-                  for (NewFieldArguments args : newFieldArguments) {
-                    newFields.add(oldSchema.newField(
-                      args.getName(), args.getType(), args.getMap()));
-                  }
-                }
-                firstAttempt = false;
-                synchronized (oldSchema.getSchemaUpdateLock()) {
-                  newSchema = oldSchema.addFields(newFields, copyFields, true);
-                  if (null != newSchema) {
-                    getSolrCore().setLatestSchema(newSchema);
-                    success = true;
-                  } else {
-                    throw new SolrException(ErrorCode.SERVER_ERROR, "Failed to add fields.");
-                  }
-                }
-              } catch (ManagedIndexSchema.SchemaChangedInZkException e) {
-                log.debug("Schema changed while processing request, retrying");
-                oldSchema = getSolrCore().getLatestSchema();
-              }
-            }
-            waitForSchemaUpdateToPropagate(newSchema);
-          }
-        }
-      }
-    } catch (Exception e) {
-      getSolrResponse().setException(e);
-    }
-    handlePostExecution(log);
-
-    return new SolrOutputRepresentation();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/java/org/apache/solr/rest/schema/FieldResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/rest/schema/FieldResource.java b/solr/core/src/java/org/apache/solr/rest/schema/FieldResource.java
deleted file mode 100644
index 2634bbd..0000000
--- a/solr/core/src/java/org/apache/solr/rest/schema/FieldResource.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * 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.
- */
-package org.apache.solr.rest.schema;
-import org.apache.solr.cloud.ZkSolrResourceLoader;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.core.CoreDescriptor;
-import org.apache.solr.core.SolrResourceLoader;
-import org.apache.solr.rest.GETable;
-import org.apache.solr.rest.PUTable;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.schema.ManagedIndexSchema;
-import org.apache.solr.schema.SchemaField;
-import org.noggit.ObjectBuilder;
-import org.restlet.data.MediaType;
-import org.restlet.representation.Representation;
-import org.restlet.resource.ResourceException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.UnsupportedEncodingException;
-import java.lang.invoke.MethodHandles;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
-/**
- * This class responds to requests at /solr/(corename)/schema/fields/(fieldname)
- * where "fieldname" is the name of a field.
- * <p>
- * The GET method returns properties for the given fieldname.
- * The "includeDynamic" query parameter, if specified, will cause the
- * dynamic field matching the given fieldname to be returned if fieldname
- * is not explicitly declared in the schema.
- * <p>
- * The PUT method accepts field addition requests in JSON format.
- */
-public class FieldResource extends BaseFieldResource implements GETable, PUTable {
-  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
-  private boolean includeDynamic;
-  private String fieldName;
-
-  public FieldResource() {
-    super();
-  }
-
-  @Override
-  public void doInit() throws ResourceException {
-    super.doInit();
-    if (isExisting()) {
-      includeDynamic = getSolrRequest().getParams().getBool(INCLUDE_DYNAMIC_PARAM, false);
-      fieldName = (String) getRequestAttributes().get(IndexSchema.NAME);
-      try {
-        fieldName = null == fieldName ? "" : urlDecode(fieldName.trim()).trim();
-      } catch (UnsupportedEncodingException e) {
-        throw new ResourceException(e);
-      }
-    }
-  }
-
-  @Override
-  public Representation get() {
-    try {
-      if (fieldName.isEmpty()) {
-        final String message = "Field name is missing";
-        throw new SolrException(ErrorCode.BAD_REQUEST, message);
-      } else {
-        final SchemaField field;
-        if (includeDynamic) {
-          field = getSchema().getFieldOrNull(fieldName);
-        } else {
-          field = getSchema().getFields().get(fieldName);
-        }
-        if (null == field) {
-          final String message = "Field '" + fieldName + "' not found.";
-          throw new SolrException(ErrorCode.NOT_FOUND, message);
-        } else {
-          getSolrResponse().add(IndexSchema.FIELD, getFieldProperties(field));
-        }
-      }
-    } catch (Exception e) {
-      getSolrResponse().setException(e);
-    }
-    handlePostExecution(log);
-
-    return new SolrOutputRepresentation();
-  }
-
-  /**
-   * Accepts JSON add field request, to URL
-   */
-  @Override
-  public Representation put(Representation entity) {
-    try {
-      if (!getSchema().isMutable()) {
-        final String message = "This IndexSchema is not mutable.";
-        throw new SolrException(ErrorCode.BAD_REQUEST, message);
-      } else {
-        if (null == entity.getMediaType()) {
-          entity.setMediaType(MediaType.APPLICATION_JSON);
-        }
-        if (!entity.getMediaType().equals(MediaType.APPLICATION_JSON, true)) {
-          String message = "Only media type " + MediaType.APPLICATION_JSON.toString() + " is accepted."
-              + "  Request has media type " + entity.getMediaType().toString() + ".";
-          log.error(message);
-          throw new SolrException(ErrorCode.BAD_REQUEST, message);
-        } else {
-          Object object = ObjectBuilder.fromJSON(entity.getText());
-          if (!(object instanceof Map)) {
-            String message = "Invalid JSON type " + object.getClass().getName() + ", expected Map of the form"
-                + " (ignore the backslashes): {\"type\":\"text_general\", ...}, either with or"
-                + " without a \"name\" mapping.  If the \"name\" is specified, it must match the"
-                + " name given in the request URL: /schema/fields/(name)";
-            log.error(message);
-            throw new SolrException(ErrorCode.BAD_REQUEST, message);
-          } else {
-            Map<String, Object> map = (Map<String, Object>) object;
-            if (1 == map.size() && map.containsKey(IndexSchema.FIELD)) {
-              map = (Map<String, Object>) map.get(IndexSchema.FIELD);
-            }
-            String bodyFieldName;
-            if (null != (bodyFieldName = (String) map.remove(IndexSchema.NAME)) && !fieldName.equals(bodyFieldName)) {
-              String message = "Field name in the request body '" + bodyFieldName
-                  + "' doesn't match field name in the request URL '" + fieldName + "'";
-              log.error(message);
-              throw new SolrException(ErrorCode.BAD_REQUEST, message);
-            } else {
-              String fieldType;
-              if (null == (fieldType = (String) map.remove(IndexSchema.TYPE))) {
-                String message = "Missing '" + IndexSchema.TYPE + "' mapping.";
-                log.error(message);
-                throw new SolrException(ErrorCode.BAD_REQUEST, message);
-              } else {
-                ManagedIndexSchema oldSchema = (ManagedIndexSchema) getSchema();
-                Object copies = map.get(IndexSchema.COPY_FIELDS);
-                List<String> copyFieldNames = null;
-                if (copies != null) {
-                  if (copies instanceof List) {
-                    copyFieldNames = (List<String>) copies;
-                  } else if (copies instanceof String) {
-                    copyFieldNames = Collections.singletonList(copies.toString());
-                  } else {
-                    String message = "Invalid '" + IndexSchema.COPY_FIELDS + "' type.";
-                    log.error(message);
-                    throw new SolrException(ErrorCode.BAD_REQUEST, message);
-                  }
-                }
-                if (copyFieldNames != null) {
-                  map.remove(IndexSchema.COPY_FIELDS);
-                }
-
-                IndexSchema newSchema = null;
-                boolean success = false;
-                while (!success) {
-                  try {
-                    SchemaField newField = oldSchema.newField(fieldName, fieldType, map);
-                    synchronized (oldSchema.getSchemaUpdateLock()) {
-                      newSchema = oldSchema.addField(newField, copyFieldNames);
-                      if (null != newSchema) {
-                        getSolrCore().setLatestSchema(newSchema);
-                        success = true;
-                      } else {
-                        throw new SolrException(ErrorCode.SERVER_ERROR, "Failed to add field.");
-                      }
-                    }
-                  } catch (ManagedIndexSchema.SchemaChangedInZkException e) {
-                    log.debug("Schema changed while processing request, retrying");
-                    oldSchema = (ManagedIndexSchema)getSolrCore().getLatestSchema();
-                  }
-                }
-                waitForSchemaUpdateToPropagate(newSchema);
-              }
-            }
-          }
-        }
-      }
-    } catch (Exception e) {
-      getSolrResponse().setException(e);
-    }
-    handlePostExecution(log);
-
-    return new SolrOutputRepresentation();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/java/org/apache/solr/rest/schema/FieldTypeCollectionResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/rest/schema/FieldTypeCollectionResource.java b/solr/core/src/java/org/apache/solr/rest/schema/FieldTypeCollectionResource.java
deleted file mode 100644
index d2eb1bd..0000000
--- a/solr/core/src/java/org/apache/solr/rest/schema/FieldTypeCollectionResource.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * 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.
- */
-package org.apache.solr.rest.schema;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.solr.rest.GETable;
-import org.apache.solr.rest.POSTable;
-import org.apache.solr.schema.FieldType;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.schema.ManagedIndexSchema;
-import org.apache.solr.schema.SchemaField;
-import org.noggit.ObjectBuilder;
-import org.restlet.data.MediaType;
-import org.restlet.representation.Representation;
-import org.restlet.resource.ResourceException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * This class responds to requests at /solr/(corename)/schema/fieldtypes
- * 
- * The GET method returns properties for all field types defined in the schema.
- */
-public class FieldTypeCollectionResource extends BaseFieldTypeResource implements GETable, POSTable {
-  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-  
-  private Map<String,List<String>> fieldsByFieldType;
-  private Map<String,List<String>> dynamicFieldsByFieldType;
-
-  public FieldTypeCollectionResource() {
-    super();
-  }
-
-  @Override
-  public void doInit() throws ResourceException {
-    super.doInit();
-    if (isExisting()) {
-      fieldsByFieldType = getFieldsByFieldType();
-      dynamicFieldsByFieldType = getDynamicFieldsByFieldType();
-    }
-  }
-  
-  @Override
-  public Representation get() {
-    try {
-      List<SimpleOrderedMap<Object>> props = new ArrayList<>();
-      Map<String,FieldType> sortedFieldTypes = new TreeMap<>(getSchema().getFieldTypes());
-      for (FieldType fieldType : sortedFieldTypes.values()) {
-        props.add(getFieldTypeProperties(fieldType));
-      }
-      getSolrResponse().add(IndexSchema.FIELD_TYPES, props);
-    } catch (Exception e) {
-      getSolrResponse().setException(e);
-    }
-    handlePostExecution(log);
-
-    return new SolrOutputRepresentation();
-  }
-
-  /** Returns field lists from the map constructed in doInit() */
-  @Override
-  protected List<String> getFieldsWithFieldType(FieldType fieldType) {
-    List<String> fields = fieldsByFieldType.get(fieldType.getTypeName());
-    if (null == fields) {
-      fields = Collections.emptyList();
-    }
-    return fields;
-  }
-
-  /** Returns dynamic field lists from the map constructed in doInit() */
-  @Override
-  protected List<String> getDynamicFieldsWithFieldType(FieldType fieldType) {
-    List<String> dynamicFields = dynamicFieldsByFieldType.get(fieldType.getTypeName());
-    if (null == dynamicFields) {
-      dynamicFields = Collections.emptyList();
-    }
-    return dynamicFields;
-  }
-
-  /**
-   * Returns a map from field type names to a sorted list of fields that use the field type.
-   * The map only includes field types that are used by at least one field.  
-   */
-  private Map<String,List<String>> getFieldsByFieldType() {
-    Map<String,List<String>> fieldsByFieldType = new HashMap<>();
-    for (SchemaField schemaField : getSchema().getFields().values()) {
-      final String fieldType = schemaField.getType().getTypeName();
-      List<String> fields = fieldsByFieldType.get(fieldType);
-      if (null == fields) {
-        fields = new ArrayList<>();
-        fieldsByFieldType.put(fieldType, fields);
-      }
-      fields.add(schemaField.getName());
-    }
-    for (List<String> fields : fieldsByFieldType.values()) {
-      Collections.sort(fields);
-    }
-    return fieldsByFieldType;
-  }
-
-  /**
-   * Returns a map from field type names to a list of dynamic fields that use the field type.
-   * The map only includes field types that are used by at least one dynamic field.  
-   */
-  private Map<String,List<String>> getDynamicFieldsByFieldType() {
-    Map<String,List<String>> dynamicFieldsByFieldType = new HashMap<>();
-    for (SchemaField schemaField : getSchema().getDynamicFieldPrototypes()) {
-      final String fieldType = schemaField.getType().getTypeName();
-      List<String> dynamicFields = dynamicFieldsByFieldType.get(fieldType);
-      if (null == dynamicFields) {
-        dynamicFields = new ArrayList<>();
-        dynamicFieldsByFieldType.put(fieldType, dynamicFields);
-      }
-      dynamicFields.add(schemaField.getName());
-    }
-    return dynamicFieldsByFieldType;
-  }
-  
-  @SuppressWarnings("unchecked")
-  @Override
-  public Representation post(Representation entity) {
-    try {
-      if (!getSchema().isMutable()) {
-        final String message = "This IndexSchema is not mutable.";
-        throw new SolrException(ErrorCode.BAD_REQUEST, message);
-      }
-      
-      if (null == entity.getMediaType())
-        entity.setMediaType(MediaType.APPLICATION_JSON);
-      
-      if (!entity.getMediaType().equals(MediaType.APPLICATION_JSON, true)) {
-        String message = "Only media type " + MediaType.APPLICATION_JSON.toString() + " is accepted."
-            + "  Request has media type " + entity.getMediaType().toString() + ".";
-        log.error(message);
-        throw new SolrException(ErrorCode.BAD_REQUEST, message);
-      }
-      
-      Object object = ObjectBuilder.fromJSON(entity.getText());
-      if (!(object instanceof List)) {
-        String message = "Invalid JSON type " + object.getClass().getName() 
-            + ", expected List of field type definitions in the form of"
-            + " (ignore the backslashes): [{\"name\":\"text_general\",\"class\":\"solr.TextField\", ...}, {...}, ...]";
-        log.error(message);
-        throw new SolrException(ErrorCode.BAD_REQUEST, message);
-      }
-      
-      List<Map<String, Object>> fieldTypeList = (List<Map<String, Object>>) object;
-      if (fieldTypeList.size() > 0)
-        addOrUpdateFieldTypes(fieldTypeList);
-    } catch (Exception e) {
-      getSolrResponse().setException(e);
-    }
-    handlePostExecution(log);
-
-    return new SolrOutputRepresentation();
-  }  
-  
-  @SuppressWarnings("unchecked")
-  protected void addOrUpdateFieldTypes(List<Map<String, Object>> fieldTypeList) throws Exception {
-    List<FieldType> newFieldTypes = new ArrayList<>(fieldTypeList.size());
-    ManagedIndexSchema oldSchema = (ManagedIndexSchema) getSchema();
-    for (Map<String,Object> fieldTypeJson : fieldTypeList) {
-      if (1 == fieldTypeJson.size() && fieldTypeJson.containsKey(IndexSchema.FIELD_TYPE)) {
-        fieldTypeJson = (Map<String, Object>) fieldTypeJson.get(IndexSchema.FIELD_TYPE);
-      }
-      FieldType newFieldType = 
-          FieldTypeResource.buildFieldTypeFromJson(oldSchema, 
-              (String)fieldTypeJson.get(IndexSchema.NAME), fieldTypeJson);
-      newFieldTypes.add(newFieldType);
-    }
-    // now deploy the added types (all or nothing)
-    addNewFieldTypes(newFieldTypes, oldSchema);
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/java/org/apache/solr/rest/schema/FieldTypeResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/rest/schema/FieldTypeResource.java b/solr/core/src/java/org/apache/solr/rest/schema/FieldTypeResource.java
deleted file mode 100644
index 361c8c2..0000000
--- a/solr/core/src/java/org/apache/solr/rest/schema/FieldTypeResource.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * 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.
- */
-package org.apache.solr.rest.schema;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.rest.GETable;
-import org.apache.solr.rest.PUTable;
-import org.apache.solr.schema.FieldType;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.schema.ManagedIndexSchema;
-import org.apache.solr.schema.SchemaField;
-import org.noggit.ObjectBuilder;
-import org.restlet.data.MediaType;
-import org.restlet.representation.Representation;
-import org.restlet.resource.ResourceException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.UnsupportedEncodingException;
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-/**
- * This class responds to requests at /solr/(corename)/schema/fieldtype/(typename)
- * where "typename" is the name of a field type in the schema.
- * 
- * The GET method returns properties for the named field type.
- */
-public class FieldTypeResource extends BaseFieldTypeResource implements GETable, PUTable {
-  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
-  private String typeName;
-
-  public FieldTypeResource() {
-    super();
-  }
-
-  @Override
-  public void doInit() throws ResourceException {
-    super.doInit();
-    if (isExisting()) {
-      typeName = (String)getRequestAttributes().get(IndexSchema.NAME);
-      try {
-        typeName = null == typeName ? "" : urlDecode(typeName.trim()).trim();
-      } catch (UnsupportedEncodingException e) {
-        throw new ResourceException(e);
-      }
-    }
-  }
-
-  @Override
-  public Representation get() {
-    try {
-      if (typeName.isEmpty()) {
-        final String message = "Field type name is missing";
-        throw new SolrException(ErrorCode.BAD_REQUEST, message);
-      } else {
-        FieldType fieldType = getSchema().getFieldTypes().get(typeName);
-        if (null == fieldType) {
-          final String message = "Field type '" + typeName + "' not found.";
-          throw new SolrException(ErrorCode.NOT_FOUND, message);
-        }
-        getSolrResponse().add(IndexSchema.FIELD_TYPE, getFieldTypeProperties(fieldType));
-      }
-    } catch (Exception e) {
-      getSolrResponse().setException(e);
-    }
-    handlePostExecution(log);
-
-    return new SolrOutputRepresentation();
-  }
-
-  /** 
-   * Returns a field list using the given field type by iterating over all fields
-   * defined in the schema.
-   */
-  @Override
-  protected List<String> getFieldsWithFieldType(FieldType fieldType) {
-    List<String> fields = new ArrayList<>();
-    for (SchemaField schemaField : getSchema().getFields().values()) {
-      if (schemaField.getType().getTypeName().equals(fieldType.getTypeName())) {
-        fields.add(schemaField.getName());
-      }
-    }
-    Collections.sort(fields);
-    return fields;
-  }
-
-  /**
-   * Returns a dynamic field list using the given field type by iterating over all
-   * dynamic fields defined in the schema. 
-   */
-  @Override
-  protected List<String> getDynamicFieldsWithFieldType(FieldType fieldType) {
-    List<String> dynamicFields = new ArrayList<>();
-    for (SchemaField prototype : getSchema().getDynamicFieldPrototypes()) {
-      if (prototype.getType().getTypeName().equals(fieldType.getTypeName())) {
-        dynamicFields.add(prototype.getName());
-      }
-    }
-    return dynamicFields; // Don't sort these - they're matched in order
-  }
-  
-  /**
-   * Accepts JSON add fieldtype request, to URL
-   */
-  @SuppressWarnings("unchecked")
-  @Override
-  public Representation put(Representation entity) {
-    try {
-      if (!getSchema().isMutable()) {
-        final String message = "This IndexSchema is not mutable.";
-        throw new SolrException(ErrorCode.BAD_REQUEST, message);
-      }
-      
-      if (null == entity.getMediaType())
-        entity.setMediaType(MediaType.APPLICATION_JSON);
-      
-      if (!entity.getMediaType().equals(MediaType.APPLICATION_JSON, true)) {
-        String message = "Only media type " + MediaType.APPLICATION_JSON.toString() + " is accepted."
-            + "  Request has media type " + entity.getMediaType().toString() + ".";
-        log.error(message);
-        throw new SolrException(ErrorCode.BAD_REQUEST, message);
-      }
-      
-      Object object = ObjectBuilder.fromJSON(entity.getText());
-      if (!(object instanceof Map)) {
-        String message = "Invalid JSON type " + object.getClass().getName() + ", expected Map of the form"
-            + " (ignore the backslashes): {\"name\":\"text_general\", \"class\":\"solr.TextField\" ...},"
-            + " either with or without a \"name\" mapping.  If the \"name\" is specified, it must match the"
-            + " name given in the request URL: /schema/fieldtypes/(name)";
-        log.error(message);
-        throw new SolrException(ErrorCode.BAD_REQUEST, message);
-      }
-      
-      // basic validation passed, let's try to create it!
-      addOrUpdateFieldType((Map<String, Object>)object);
-      
-    } catch (Exception e) {
-      getSolrResponse().setException(e);
-    }
-    handlePostExecution(log);
-
-    return new SolrOutputRepresentation();
-  }
-  
-  protected void addOrUpdateFieldType(Map<String,Object> fieldTypeJson) {
-    ManagedIndexSchema oldSchema = (ManagedIndexSchema) getSchema();
-    FieldType newFieldType = buildFieldTypeFromJson(oldSchema, typeName, fieldTypeJson);
-    addNewFieldTypes(Collections.singletonList(newFieldType), oldSchema);
-  }
-
-  /**
-   * Builds a FieldType definition from a JSON object.
-   */
-  @SuppressWarnings("unchecked")
-  static FieldType buildFieldTypeFromJson(ManagedIndexSchema oldSchema, String fieldTypeName, Map<String,Object> fieldTypeJson) {
-    if (1 == fieldTypeJson.size() && fieldTypeJson.containsKey(IndexSchema.FIELD_TYPE)) {
-      fieldTypeJson = (Map<String, Object>)fieldTypeJson.get(IndexSchema.FIELD_TYPE);
-    }
-
-    String bodyTypeName = (String) fieldTypeJson.get(IndexSchema.NAME);
-    if (bodyTypeName == null) {
-      // must provide the name in the JSON for converting to the XML format needed
-      // to create FieldType objects using the FieldTypePluginLoader
-      fieldTypeJson.put(IndexSchema.NAME, fieldTypeName);
-    } else {
-      // if they provide it in the JSON, then it must match the value from the path
-      if (!fieldTypeName.equals(bodyTypeName)) {
-        String message = "Field type name in the request body '" + bodyTypeName
-            + "' doesn't match field type name in the request URL '" + fieldTypeName + "'";
-        log.error(message);
-        throw new SolrException(ErrorCode.BAD_REQUEST, message);
-      }
-    }
-
-    String className = (String)fieldTypeJson.get(FieldType.CLASS_NAME);
-    if (className == null) {
-      String message = "Missing required '" + FieldType.CLASS_NAME + "' property!";
-      log.error(message);
-      throw new SolrException(ErrorCode.BAD_REQUEST, message);
-    }
-
-    return oldSchema.newFieldType(fieldTypeName, className, fieldTypeJson);
-  }
-}


[25/50] [abbrv] lucene-solr git commit: SOLR-8782: Improve async collections API

Posted by no...@apache.org.
SOLR-8782: Improve async collections API


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

Branch: refs/heads/apiv2
Commit: 5b7be9d16abf72052910a63e6d79debd8af5a7c1
Parents: a0a571c
Author: Alan Woodward <ro...@apache.org>
Authored: Mon Mar 7 16:00:40 2016 +0000
Committer: Alan Woodward <ro...@apache.org>
Committed: Tue Mar 8 10:53:29 2016 +0000

----------------------------------------------------------------------
 solr/CHANGES.txt                                |   4 +
 .../configsets/cloud-minimal/conf/schema.xml    |  32 +
 .../cloud-minimal/conf/solrconfig.xml           |  48 ++
 .../CollectionsAPIAsyncDistributedZkTest.java   | 174 ++---
 .../solr/security/BasicAuthIntegrationTest.java |   2 +-
 .../solrj/request/CollectionAdminRequest.java   | 691 +++++++++++++------
 6 files changed, 622 insertions(+), 329 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5b7be9d1/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 7893b88..b71c63b 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -22,6 +22,10 @@ See the Quick Start guide at http://lucene.apache.org/solr/quickstart.html
 ==================  6.1.0 ==================
 Detailed Change List
 ----------------------
+* SOLR-8782: Add asynchronous sugar methods to the SolrJ Collections API.  You
+  can now call .processAsync() to run a method asynchronously, or
+  .processAndWait() to wait for a call to finish without holding HTTP
+  collections open.  (Alan Woodward)
 
 New Features
 ----------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5b7be9d1/solr/core/src/test-files/solr/configsets/cloud-minimal/conf/schema.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/cloud-minimal/conf/schema.xml b/solr/core/src/test-files/solr/configsets/cloud-minimal/conf/schema.xml
new file mode 100644
index 0000000..2a276af
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/cloud-minimal/conf/schema.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ 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.
+-->
+<schema name="minimal" version="1.1">
+ <types>
+  <fieldType name="string" class="solr.StrField"/>
+  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+ </types>
+ <fields>
+  <dynamicField name="*" type="string" indexed="true" stored="true" />
+  <!-- for versioning -->
+  <field name="_version_" type="long" indexed="true" stored="true"/>
+  <field name="_root_" type="int" indexed="true" stored="true" multiValued="false" required="false"/>
+  <field name="id" type="string" indexed="true" stored="true"/>
+ </fields>
+ <uniqueKey>id</uniqueKey>
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5b7be9d1/solr/core/src/test-files/solr/configsets/cloud-minimal/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/cloud-minimal/conf/solrconfig.xml b/solr/core/src/test-files/solr/configsets/cloud-minimal/conf/solrconfig.xml
new file mode 100644
index 0000000..059e58f
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/cloud-minimal/conf/solrconfig.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" ?>
+
+<!--
+ 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.
+-->
+
+<!-- Minimal solrconfig.xml with /select, /admin and /update only -->
+
+<config>
+
+  <dataDir>${solr.data.dir:}</dataDir>
+
+  <directoryFactory name="DirectoryFactory"
+                    class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/>
+  <schemaFactory class="ClassicIndexSchemaFactory"/>
+
+  <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
+
+  <updateHandler class="solr.DirectUpdateHandler2">
+    <commitWithin>
+      <softCommit>${solr.commitwithin.softcommit:true}</softCommit>
+    </commitWithin>
+    <updateLog></updateLog>
+  </updateHandler>
+
+  <requestHandler name="/select" class="solr.SearchHandler">
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+      <str name="indent">true</str>
+      <str name="df">text</str>
+    </lst>
+
+  </requestHandler>
+</config>
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5b7be9d1/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIAsyncDistributedZkTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIAsyncDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIAsyncDistributedZkTest.java
index 493b298..dcb115a 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIAsyncDistributedZkTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIAsyncDistributedZkTest.java
@@ -21,90 +21,80 @@ import java.util.List;
 
 import org.apache.lucene.util.LuceneTestCase.Slow;
 import org.apache.lucene.util.TestUtil;
-import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
-import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest.Create;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest.SplitShard;
 import org.apache.solr.client.solrj.response.RequestStatusState;
-import org.apache.solr.client.solrj.response.CollectionAdminResponse;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.cloud.Slice;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 /**
  * Tests the Cloud Collections API.
  */
 @Slow
-public class CollectionsAPIAsyncDistributedZkTest extends AbstractFullDistribZkTestBase {
+public class CollectionsAPIAsyncDistributedZkTest extends SolrCloudTestCase {
+
   private static final int MAX_TIMEOUT_SECONDS = 60;
 
-  public CollectionsAPIAsyncDistributedZkTest() {
-    sliceCount = 1;
+  @BeforeClass
+  public static void setupCluster() throws Exception {
+    configureCluster(2)
+        .addConfig("conf1", TEST_PATH().resolve("configsets").resolve("cloud-minimal").resolve("conf"))
+        .configure();
   }
 
   @Test
-  @ShardsFixed(num = 1)
   public void testSolrJAPICalls() throws Exception {
-    try (SolrClient client = createNewSolrClient("", getBaseUrl((HttpSolrClient) clients.get(0)))) {
-      Create createCollectionRequest = new Create()
-              .setCollectionName("testasynccollectioncreation")
-              .setNumShards(1)
-              .setConfigName("conf1")
-              .setAsyncId("1001");
-      createCollectionRequest.process(client);
-  
-      RequestStatusState state = getRequestStateAfterCompletion("1001", MAX_TIMEOUT_SECONDS, client);
-  
-      assertSame("CreateCollection task did not complete!", RequestStatusState.COMPLETED, state);
-  
-      createCollectionRequest = new Create()
-              .setCollectionName("testasynccollectioncreation")
-              .setNumShards(1)
-              .setConfigName("conf1")
-              .setAsyncId("1002");
-      createCollectionRequest.process(client);
-  
-      state = getRequestStateAfterCompletion("1002", MAX_TIMEOUT_SECONDS, client);
-  
-      assertSame("Recreating a collection with the same should have failed.", RequestStatusState.FAILED, state);
-  
-      CollectionAdminRequest.AddReplica addReplica = new CollectionAdminRequest.AddReplica()
-              .setCollectionName("testasynccollectioncreation")
-              .setShardName("shard1")
-              .setAsyncId("1003");
-      client.request(addReplica);
-      state = getRequestStateAfterCompletion("1003", MAX_TIMEOUT_SECONDS, client);
-      assertSame("Add replica did not complete", RequestStatusState.COMPLETED, state);
-  
-      SplitShard splitShardRequest = new SplitShard()
-              .setCollectionName("testasynccollectioncreation")
-              .setShardName("shard1")
-              .setAsyncId("1004");
-      splitShardRequest.process(client);
-  
-      state = getRequestStateAfterCompletion("1004", MAX_TIMEOUT_SECONDS * 2, client);
-  
-      assertEquals("Shard split did not complete. Last recorded state: " + state, RequestStatusState.COMPLETED, state);
-    }
+
+    final CloudSolrClient client = cluster.getSolrClient();
+
+    RequestStatusState state = new Create()
+        .setCollectionName("testasynccollectioncreation")
+        .setNumShards(1)
+        .setReplicationFactor(1)
+        .setConfigName("conf1")
+        .processAndWait(client, MAX_TIMEOUT_SECONDS);
+    assertSame("CreateCollection task did not complete!", RequestStatusState.COMPLETED, state);
+
+    state = new Create()
+        .setCollectionName("testasynccollectioncreation")
+        .setNumShards(1)
+        .setConfigName("conf1")
+        .processAndWait(client, MAX_TIMEOUT_SECONDS);
+    assertSame("Recreating a collection with the same should have failed.", RequestStatusState.FAILED, state);
+
+    state = new CollectionAdminRequest.AddReplica()
+        .setCollectionName("testasynccollectioncreation")
+        .setShardName("shard1")
+        .processAndWait(client, MAX_TIMEOUT_SECONDS);
+    assertSame("Add replica did not complete", RequestStatusState.COMPLETED, state);
+
+    state = new SplitShard()
+        .setCollectionName("testasynccollectioncreation")
+        .setShardName("shard1")
+        .processAndWait(client, MAX_TIMEOUT_SECONDS * 2);
+    assertEquals("Shard split did not complete. Last recorded state: " + state, RequestStatusState.COMPLETED, state);
+
   }
 
   @Test
   public void testAsyncRequests() throws Exception {
-    String collection = "testAsyncOperations";
 
-    Create createCollectionRequest = new Create()
+    final String collection = "testAsyncOperations";
+    final CloudSolrClient client = cluster.getSolrClient();
+
+    RequestStatusState state = new Create()
         .setCollectionName(collection)
         .setNumShards(1)
         .setRouterName("implicit")
         .setShards("shard1")
         .setConfigName("conf1")
-        .setAsyncId("42");
-    CollectionAdminResponse response = createCollectionRequest.process(cloudClient);
-    assertEquals("42", response.getResponse().get("requestid"));
-    RequestStatusState state = getRequestStateAfterCompletion("42", MAX_TIMEOUT_SECONDS, cloudClient);
+        .processAndWait(client, MAX_TIMEOUT_SECONDS);
     assertSame("CreateCollection task did not complete!", RequestStatusState.COMPLETED, state);
 
     //Add a few documents to shard1
@@ -116,59 +106,48 @@ public class CollectionsAPIAsyncDistributedZkTest extends AbstractFullDistribZkT
       doc.addField("_route_", "shard1");
       docs.add(doc);
     }
-    cloudClient.add(collection, docs);
-    cloudClient.commit(collection);
+    client.add(collection, docs);
+    client.commit(collection);
 
     SolrQuery query = new SolrQuery("*:*");
     query.set("shards", "shard1");
-    assertEquals(numDocs, cloudClient.query(collection, query).getResults().getNumFound());
+    assertEquals(numDocs, client.query(collection, query).getResults().getNumFound());
 
-    CollectionAdminRequest.Reload reloadCollection = new CollectionAdminRequest.Reload();
-    reloadCollection.setCollectionName(collection).setAsyncId("43");
-    response = reloadCollection.process(cloudClient);
-    assertEquals("43", response.getResponse().get("requestid"));
-    state = getRequestStateAfterCompletion("43", MAX_TIMEOUT_SECONDS, cloudClient);
+    state = new CollectionAdminRequest.Reload()
+        .setCollectionName(collection)
+        .processAndWait(client, MAX_TIMEOUT_SECONDS);
     assertSame("ReloadCollection did not complete", RequestStatusState.COMPLETED, state);
 
-    CollectionAdminRequest.CreateShard createShard = new CollectionAdminRequest.CreateShard()
+    state = new CollectionAdminRequest.CreateShard()
         .setCollectionName(collection)
         .setShardName("shard2")
-        .setAsyncId("44");
-    response = createShard.process(cloudClient);
-    assertEquals("44", response.getResponse().get("requestid"));
-    state = getRequestStateAfterCompletion("44", MAX_TIMEOUT_SECONDS, cloudClient);
+        .processAndWait(client, MAX_TIMEOUT_SECONDS);
     assertSame("CreateShard did not complete", RequestStatusState.COMPLETED, state);
 
     //Add a doc to shard2 to make sure shard2 was created properly
     SolrInputDocument doc = new SolrInputDocument();
     doc.addField("id", numDocs + 1);
     doc.addField("_route_", "shard2");
-    cloudClient.add(collection, doc);
-    cloudClient.commit(collection);
+    client.add(collection, doc);
+    client.commit(collection);
     query = new SolrQuery("*:*");
     query.set("shards", "shard2");
-    assertEquals(1, cloudClient.query(collection, query).getResults().getNumFound());
+    assertEquals(1, client.query(collection, query).getResults().getNumFound());
 
-    CollectionAdminRequest.DeleteShard deleteShard = new CollectionAdminRequest.DeleteShard()
+    state = new CollectionAdminRequest.DeleteShard()
         .setCollectionName(collection)
         .setShardName("shard2")
-        .setAsyncId("45");
-    response = deleteShard.process(cloudClient);
-    assertEquals("45", response.getResponse().get("requestid"));
-    state = getRequestStateAfterCompletion("45", MAX_TIMEOUT_SECONDS, cloudClient);
+        .processAndWait(client, MAX_TIMEOUT_SECONDS);
     assertSame("DeleteShard did not complete", RequestStatusState.COMPLETED, state);
 
-    CollectionAdminRequest.AddReplica addReplica = new CollectionAdminRequest.AddReplica()
+    state = new CollectionAdminRequest.AddReplica()
         .setCollectionName(collection)
         .setShardName("shard1")
-        .setAsyncId("46");
-    response = addReplica.process(cloudClient);
-    assertEquals("46", response.getResponse().get("requestid"));
-    state = getRequestStateAfterCompletion("46", MAX_TIMEOUT_SECONDS, cloudClient);
+        .processAndWait(client, MAX_TIMEOUT_SECONDS);
     assertSame("AddReplica did not complete", RequestStatusState.COMPLETED, state);
 
     //cloudClient watch might take a couple of seconds to reflect it
-    Slice shard1 = cloudClient.getZkStateReader().getClusterState().getSlice(collection, "shard1");
+    Slice shard1 = client.getZkStateReader().getClusterState().getSlice(collection, "shard1");
     int count = 0;
     while (shard1.getReplicas().size() != 2) {
       if (count++ > 1000) {
@@ -177,51 +156,40 @@ public class CollectionsAPIAsyncDistributedZkTest extends AbstractFullDistribZkT
       Thread.sleep(100);
     }
 
-    CollectionAdminRequest.CreateAlias createAlias = new CollectionAdminRequest.CreateAlias()
+    state = new CollectionAdminRequest.CreateAlias()
         .setAliasName("myalias")
         .setAliasedCollections(collection)
-        .setAsyncId("47");
-    response = createAlias.process(cloudClient);
-    assertEquals("47", response.getResponse().get("requestid"));
-    state = getRequestStateAfterCompletion("47", MAX_TIMEOUT_SECONDS, cloudClient);
+        .processAndWait(client, MAX_TIMEOUT_SECONDS);
     assertSame("CreateAlias did not complete", RequestStatusState.COMPLETED, state);
 
     query = new SolrQuery("*:*");
     query.set("shards", "shard1");
-    assertEquals(numDocs, cloudClient.query("myalias", query).getResults().getNumFound());
+    assertEquals(numDocs, client.query("myalias", query).getResults().getNumFound());
 
-    CollectionAdminRequest.DeleteAlias deleteAlias = new CollectionAdminRequest.DeleteAlias()
+    state = new CollectionAdminRequest.DeleteAlias()
         .setAliasName("myalias")
-        .setAsyncId("48");
-    response = deleteAlias.process(cloudClient);
-    assertEquals("48", response.getResponse().get("requestid"));
-    state = getRequestStateAfterCompletion("48", MAX_TIMEOUT_SECONDS, cloudClient);
+        .processAndWait(client, MAX_TIMEOUT_SECONDS);
     assertSame("DeleteAlias did not complete", RequestStatusState.COMPLETED, state);
 
     try {
-      cloudClient.query("myalias", query);
+      client.query("myalias", query);
       fail("Alias should not exist");
     } catch (SolrException e) {
       //expected
     }
 
     String replica = shard1.getReplicas().iterator().next().getName();
-    CollectionAdminRequest.DeleteReplica deleteReplica = new CollectionAdminRequest.DeleteReplica()
+    state = new CollectionAdminRequest.DeleteReplica()
         .setCollectionName(collection)
         .setShardName("shard1")
         .setReplica(replica)
-        .setAsyncId("47");
-    response = deleteReplica.process(cloudClient);
-    assertEquals("47", response.getResponse().get("requestid"));
-    state = getRequestStateAfterCompletion("47", MAX_TIMEOUT_SECONDS, cloudClient);
+        .processAndWait(client, MAX_TIMEOUT_SECONDS);
     assertSame("DeleteReplica did not complete", RequestStatusState.COMPLETED, state);
 
-    CollectionAdminRequest.Delete deleteCollection = new CollectionAdminRequest.Delete()
+    state = new CollectionAdminRequest.Delete()
         .setCollectionName(collection)
-        .setAsyncId("48");
-    response = deleteCollection.process(cloudClient);
-    assertEquals("48", response.getResponse().get("requestid"));
-    state = getRequestStateAfterCompletion("48", MAX_TIMEOUT_SECONDS, cloudClient);
+        .processAndWait(client, MAX_TIMEOUT_SECONDS);
     assertSame("DeleteCollection did not complete", RequestStatusState.COMPLETED, state);
   }
+
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5b7be9d1/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
index c5d27a9..ab02a3e 100644
--- a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
@@ -161,7 +161,7 @@ public class BasicAuthIntegrationTest extends TestMiniSolrCloudClusterBase {
     verifySecurityStatus(cl, baseUrl + authzPrefix, "authorization/permissions[2]/name", "collection-admin-edit", 20);
 
     CollectionAdminRequest.Reload reload = new CollectionAdminRequest.Reload();
-    reload.setCollectionName(cloudSolrClient.getDefaultCollection());
+    reload.setCollectionName(defaultCollName);
 
     HttpSolrClient solrClient = new HttpSolrClient(baseUrl);
     try {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5b7be9d1/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
index a7d71ca..c9c8c39 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
@@ -21,10 +21,15 @@ import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Properties;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.SolrResponse;
+import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.response.CollectionAdminResponse;
+import org.apache.solr.client.solrj.response.RequestStatusState;
 import org.apache.solr.client.solrj.util.SolrIdentifierValidator;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.cloud.DocCollection;
@@ -37,33 +42,28 @@ import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.ShardParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.ContentStream;
+import org.apache.solr.common.util.NamedList;
 
 /**
  * This class is experimental and subject to change.
  *
  * @since solr 4.5
  */
-public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q>> extends SolrRequest<CollectionAdminResponse> {
+public abstract class CollectionAdminRequest<T extends CollectionAdminResponse> extends SolrRequest<T> {
 
-  protected CollectionAction action = null;
+  protected final CollectionAction action;
 
   private static String PROPERTY_PREFIX = "property.";
 
-  protected CollectionAdminRequest setAction(CollectionAction action) {
-    this.action = action;
-    return this;
-  }
-
-  public CollectionAdminRequest() {
-    super(METHOD.GET, "/admin/collections");
+  public CollectionAdminRequest(CollectionAction action) {
+    this("/admin/collections", action);
   }
 
-  public CollectionAdminRequest(String path) {
+  public CollectionAdminRequest(String path, CollectionAction action) {
     super(METHOD.GET, path);
+    this.action = action;
   }
 
-  protected abstract Q getThis();
-
   @Override
   public SolrParams getParams() {
     if (action == null) {
@@ -79,11 +79,6 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     return null;
   }
 
-  @Override
-  protected CollectionAdminResponse createResponse(SolrClient client) {
-    return new CollectionAdminResponse();
-  }
-
   protected void addProperties(ModifiableSolrParams params, Properties props) {
     Iterator<Map.Entry<Object, Object>> iter = props.entrySet().iterator();
     while(iter.hasNext()) {
@@ -94,18 +89,84 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     }
   }
 
-  protected abstract static class AsyncCollectionAdminRequest <T extends CollectionAdminRequest<T>> extends CollectionAdminRequest<T> {
-    protected String asyncId = null;
+  protected abstract static class AsyncCollectionAdminRequest extends CollectionAdminRequest<CollectionAdminResponse> {
 
-    public final T setAsyncId(String asyncId) {
-      this.asyncId = asyncId;
-      return getThis();
+    public AsyncCollectionAdminRequest(CollectionAction action) {
+      super(action);
     }
 
+    @Override
+    protected CollectionAdminResponse createResponse(SolrClient client) {
+      return new CollectionAdminResponse();
+    }
+
+    private static String generateAsyncId() {
+      return UUID.randomUUID().toString();
+    }
+
+    protected String asyncId = null;
+
     public String getAsyncId() {
       return asyncId;
     }
 
+    /**
+     * @deprecated Use {@link #processAsync(String, SolrClient)} or {@link #processAsync(SolrClient)}
+     */
+    @Deprecated
+    public abstract AsyncCollectionAdminRequest setAsyncId(String id);
+
+    /**
+     * Process this request asynchronously, generating and returning a request id
+     * @param client a Solr client
+     * @return the request id
+     * @see CollectionAdminRequest.RequestStatus
+     */
+    public String processAsync(SolrClient client) throws IOException, SolrServerException {
+      return processAsync(generateAsyncId(), client);
+    }
+
+    /**
+     * Process this request asynchronously, using a specified request id
+     * @param asyncId the request id
+     * @param client a Solr client
+     * @return the request id
+     */
+    public String processAsync(String asyncId, SolrClient client) throws IOException, SolrServerException {
+      this.asyncId = asyncId;
+      NamedList<Object> resp = client.request(this);
+      if (resp.get("error") != null) {
+        throw new SolrServerException((String)resp.get("error"));
+      }
+      return (String) resp.get("requestid");
+    }
+
+    /**
+     * Send this request to a Solr server, and wait (up to a timeout) for the request to
+     * complete or fail
+     * @param client a Solr client
+     * @param timeoutSeconds the maximum time to wait
+     * @return the status of the request on completion or timeout
+     */
+    public RequestStatusState processAndWait(SolrClient client, long timeoutSeconds)
+        throws SolrServerException, InterruptedException, IOException {
+      return processAndWait(generateAsyncId(), client, timeoutSeconds);
+    }
+
+    /**
+     * Send this request to a Solr server, and wait (up to a timeout) for the request to
+     * complete or fail
+     * @param asyncId an id for the request
+     * @param client a Solr client
+     * @param timeoutSeconds the maximum time to wait
+     * @return the status of the request on completion or timeout
+     */
+    public RequestStatusState processAndWait(String asyncId, SolrClient client, long timeoutSeconds)
+        throws IOException, SolrServerException, InterruptedException {
+      processAsync(asyncId, client);
+      return new RequestStatus().setRequestId(asyncId).waitFor(client, timeoutSeconds);
+    }
+
     @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
@@ -116,121 +177,110 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     }
   }
 
-  //---------------------------------------------------------------------------------------
-  //
-  //---------------------------------------------------------------------------------------
+  protected abstract static class AsyncCollectionSpecificAdminRequest extends AsyncCollectionAdminRequest {
 
-  protected abstract static class CollectionSpecificAdminRequest <T extends CollectionAdminRequest<T>> extends CollectionAdminRequest<T> {
-    protected String collection = null;
+    protected String collection;
 
-    public T setCollectionName(String collectionName) {
-      this.collection = collectionName;
-      return getThis();
+    public AsyncCollectionSpecificAdminRequest(CollectionAction action) {
+      super(action);
     }
 
-    public final String getCollectionName() {
-      return collection;
-    }
+    public abstract AsyncCollectionSpecificAdminRequest setCollectionName(String collection);
 
     @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
+      if (collection == null)
+        throw new IllegalArgumentException("You must call setCollectionName() on this request");
       params.set(CoreAdminParams.NAME, collection);
       return params;
     }
   }
 
-  protected abstract static class CollectionSpecificAsyncAdminRequest<T extends CollectionAdminRequest<T>> extends CollectionSpecificAdminRequest<T> {
-    protected String asyncId = null;
+  protected abstract static class AsyncShardSpecificAdminRequest extends AsyncCollectionAdminRequest {
 
-    public final T setAsyncId(String asyncId) {
-      this.asyncId = asyncId;
-      return getThis();
-    }
+    protected String collection;
+    protected String shard;
 
-    public String getAsyncId() {
-      return asyncId;
+    public AsyncShardSpecificAdminRequest(CollectionAction action) {
+      super(action);
     }
 
+    public abstract AsyncShardSpecificAdminRequest setCollectionName(String collection);
+
+    public abstract AsyncShardSpecificAdminRequest setShardName(String shard);
+
     @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
-      if (asyncId != null) {
-        params.set(CommonAdminParams.ASYNC, asyncId);
-      }
+      if (collection == null)
+        throw new IllegalArgumentException("You must call setCollectionName() on this request");
+      if (shard == null)
+        throw new IllegalArgumentException("You must call setShardName() on this request");
+      params.set(CoreAdminParams.COLLECTION, collection);
+      params.set(CoreAdminParams.SHARD, shard);
       return params;
     }
   }
 
-  protected abstract static class CollectionShardAdminRequest <T extends CollectionAdminRequest<T>> extends CollectionAdminRequest<T> {
-    protected String shardName = null;
-    protected String collection = null;
+  protected abstract static class ShardSpecificAdminRequest extends CollectionAdminRequest {
 
-    public T setCollectionName(String collectionName) {
-      this.collection = collectionName;
-      return getThis();
-    }
+    protected String collection;
+    protected String shard;
 
-    public String getCollectionName() {
-      return collection;
+    public ShardSpecificAdminRequest(CollectionAction action) {
+      super(action);
     }
 
-    public T setShardName(String shard) {
-      this.shardName = shard;
-      return getThis();
-    }
+    public abstract ShardSpecificAdminRequest setCollectionName(String collection);
 
-    public String getShardName() {
-      return this.shardName;
-    }
+    public abstract ShardSpecificAdminRequest setShardName(String shard);
 
     @Override
     public SolrParams getParams() {
-      ModifiableSolrParams params = (ModifiableSolrParams) super.getParams();
+      ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
+      if (collection == null)
+        throw new IllegalArgumentException("You must call setCollectionName() on this request");
+      if (shard == null)
+        throw new IllegalArgumentException("You must call setShardName() on this request");
       params.set(CoreAdminParams.COLLECTION, collection);
-      params.set(CoreAdminParams.SHARD, shardName);
+      params.set(CoreAdminParams.SHARD, shard);
       return params;
     }
+
+    @Override
+    protected SolrResponse createResponse(SolrClient client) {
+      return new CollectionAdminResponse();
+    }
   }
 
-  protected abstract static class CollectionShardAsyncAdminRequest<T extends CollectionAdminRequest<T>> extends CollectionShardAdminRequest<T> {
-    protected String asyncId = null;
+  //---------------------------------------------------------------------------------------
+  //
+  //---------------------------------------------------------------------------------------
 
-    public final T setAsyncId(String asyncId) {
-      this.asyncId = asyncId;
-      return getThis();
-    }
 
-    public String getAsyncId() {
-      return asyncId;
+  protected abstract static class CollectionAdminRoleRequest extends AsyncCollectionAdminRequest {
+
+    protected String node;
+    protected String role;
+
+    public CollectionAdminRoleRequest(CollectionAction action) {
+      super(action);
     }
 
     @Override
-    public SolrParams getParams() {
-      ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
-      if (asyncId != null) {
-        params.set(CommonAdminParams.ASYNC, asyncId);
-      }
-      return params;
+    public CollectionAdminRoleRequest setAsyncId(String id) {
+      this.asyncId = id;
+      return this;
     }
-  }
 
-  protected abstract static class CollectionAdminRoleRequest <T extends CollectionAdminRequest<T>> extends AsyncCollectionAdminRequest<T> {
-    protected String node;
-    protected String role;
-    public T setNode(String node) {
-      this.node = node;
-      return getThis();
-    }
+    public abstract CollectionAdminRoleRequest setNode(String node);
 
     public String getNode() {
       return this.node;
     }
 
-    public T setRole(String role) {
-      this.role = role;
-      return getThis();
-    }
+    public abstract CollectionAdminRoleRequest setRole(String role);
 
     public String getRole() {
       return this.role;
@@ -249,7 +299,8 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
   /** Specific Collection API call implementations **/
 
   // CREATE request
-  public static class Create extends CollectionSpecificAsyncAdminRequest<Create> {
+  public static class Create extends AsyncCollectionSpecificAdminRequest {
+
     protected String configName = null;
     protected String createNodeSet = null;
     protected String routerName;
@@ -263,8 +314,9 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     protected Boolean autoAddReplicas;
     protected Integer stateFormat;
     private String[] rule , snitch;
+
     public Create() {
-      action = CollectionAction.CREATE;
+      super(CollectionAction.CREATE);
     }
 
     public Create setConfigName(String config) { this.configName = config; return this; }
@@ -314,7 +366,6 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
      * 
      * @throws IllegalArgumentException if the collection name contains invalid characters.
      */
-    @Override
     public Create setCollectionName(String collectionName) throws SolrException {
       if (!SolrIdentifierValidator.validateCollectionName(collectionName)) {
         throw new IllegalArgumentException(SolrIdentifierValidator.getIdentifierMessage(SolrIdentifierValidator.IdentifierType.COLLECTION,
@@ -324,6 +375,12 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
       return this;
     }
 
+    @Override
+    public Create setAsyncId(String id) {
+      this.asyncId = id;
+      return this;
+    }
+
     public Properties getProperties() {
       return properties;
     }
@@ -337,8 +394,8 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     public SolrParams getParams() {
       ModifiableSolrParams params = (ModifiableSolrParams) super.getParams();
 
-      params.set( "collection.configName", configName);
-      params.set( "createNodeSet", createNodeSet);
+      params.set("collection.configName", configName);
+      params.set("createNodeSet", createNodeSet);
       if (numShards != null) {
         params.set( ZkStateReader.NUM_SHARDS_PROP, numShards);
       }
@@ -367,51 +424,51 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
       return params;
     }
 
-    @Override
-    protected Create getThis() {
-      return this;
-    }
   }
 
   // RELOAD request
-  public static class Reload extends CollectionSpecificAsyncAdminRequest<Reload> {
+  public static class Reload extends AsyncCollectionSpecificAdminRequest {
+
     public Reload() {
-      action = CollectionAction.RELOAD;
+      super(CollectionAction.RELOAD);
     }
 
     @Override
-    public SolrParams getParams() {
-      ModifiableSolrParams params = (ModifiableSolrParams) super.getParams();
-      return params;
+    public Reload setCollectionName(String collection) {
+      this.collection = collection;
+      return this;
     }
 
     @Override
-    protected Reload getThis() {
+    public Reload setAsyncId(String id) {
+      this.asyncId = id;
       return this;
     }
   }
 
   // DELETE request
-  public static class Delete extends CollectionSpecificAsyncAdminRequest<Delete> {
+  public static class Delete extends AsyncCollectionSpecificAdminRequest {
 
     public Delete() {
-      action = CollectionAction.DELETE;
+      super(CollectionAction.DELETE);
     }
 
     @Override
-    public SolrParams getParams() {
-      ModifiableSolrParams params = (ModifiableSolrParams) super.getParams();
-      return params;
+    public Delete setCollectionName(String collection) {
+      this.collection = collection;
+      return this;
     }
 
     @Override
-    protected Delete getThis() {
+    public Delete setAsyncId(String id) {
+      this.asyncId = id;
       return this;
     }
   }
 
   // CREATESHARD request
-  public static class CreateShard extends CollectionShardAsyncAdminRequest<CreateShard> {
+  public static class CreateShard extends AsyncShardSpecificAdminRequest {
+
     protected String nodeSet;
     protected Properties properties;
 
@@ -434,9 +491,15 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     }
 
     public CreateShard() {
-      action = CollectionAction.CREATESHARD;
+      super(CollectionAction.CREATESHARD);
     }
-    
+
+    @Override
+    public CreateShard setCollectionName(String collection) {
+      this.collection = collection;
+      return this;
+    }
+
     /**
      * Provide the name of the shard to be created.
      * 
@@ -450,7 +513,13 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
         throw new IllegalArgumentException(SolrIdentifierValidator.getIdentifierMessage(SolrIdentifierValidator.IdentifierType.SHARD,
             shardName));
       }
-      this.shardName = shardName;
+      this.shard = shardName;
+      return this;
+    }
+
+    @Override
+    public CreateShard setAsyncId(String id) {
+      this.asyncId = id;
       return this;
     }
 
@@ -466,21 +535,18 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
       return params;
     }
 
-    @Override
-    protected CreateShard getThis() {
-      return this;
-    }
+
   }
 
   // SPLITSHARD request
-  public static class SplitShard extends CollectionShardAsyncAdminRequest<SplitShard> {
+  public static class SplitShard extends AsyncShardSpecificAdminRequest {
     protected String ranges;
     protected String splitKey;
 
     private Properties properties;
 
     public SplitShard() {
-      action = CollectionAction.SPLITSHARD;
+      super(CollectionAction.SPLITSHARD);
     }
 
     public SplitShard setRanges(String ranges) { this.ranges = ranges; return this; }
@@ -505,6 +571,24 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     }
 
     @Override
+    public SplitShard setCollectionName(String collection) {
+      this.collection = collection;
+      return this;
+    }
+
+    @Override
+    public SplitShard setShardName(String shard) {
+      this.shard = shard;
+      return this;
+    }
+
+    @Override
+    public SplitShard setAsyncId(String id) {
+      this.asyncId = id;
+      return this;
+    }
+
+    @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = (ModifiableSolrParams) super.getParams();
       params.set( "ranges", ranges);
@@ -518,25 +602,16 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
       return params;
     }
 
-    @Override
-    protected SplitShard getThis() {
-      return this;
-    }
   }
 
   // DELETESHARD request
-  public static class DeleteShard extends CollectionShardAsyncAdminRequest<DeleteShard> {
+  public static class DeleteShard extends AsyncShardSpecificAdminRequest {
 
     private Boolean deleteInstanceDir;
     private Boolean deleteDataDir;
 
     public DeleteShard() {
-      action = CollectionAction.DELETESHARD;
-    }
-
-    @Override
-    protected DeleteShard getThis() {
-      return this;
+      super(CollectionAction.DELETESHARD);
     }
 
     public Boolean getDeleteInstanceDir() {
@@ -558,6 +633,24 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     }
 
     @Override
+    public DeleteShard setCollectionName(String collection) {
+      this.collection = collection;
+      return this;
+    }
+
+    @Override
+    public DeleteShard setShardName(String shard) {
+      this.shard = shard;
+      return this;
+    }
+
+    @Override
+    public DeleteShard setAsyncId(String id) {
+      this.asyncId = id;
+      return this;
+    }
+
+    @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
       if (deleteInstanceDir != null) {
@@ -571,24 +664,43 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
   }
 
   // FORCELEADER request
-  public static class ForceLeader extends CollectionShardAdminRequest<ForceLeader> {
+  public static class ForceLeader extends ShardSpecificAdminRequest {
 
     public ForceLeader() {
-      action = CollectionAction.FORCELEADER;
+      super(CollectionAction.FORCELEADER);
+    }
+
+
+    @Override
+    public ForceLeader setCollectionName(String collection) {
+      this.collection = collection;
+      return this;
     }
 
     @Override
-    protected ForceLeader getThis() {
+    public ForceLeader setShardName(String shard) {
+      this.shard = shard;
       return this;
     }
+
+  }
+
+  public static class RequestStatusResponse extends CollectionAdminResponse {
+
+    public RequestStatusState getRequestStatus() {
+      NamedList innerResponse = (NamedList) getResponse().get("status");
+      return RequestStatusState.fromKey((String) innerResponse.get("state"));
+    }
+
   }
 
   // REQUESTSTATUS request
-  public static class RequestStatus extends CollectionAdminRequest<RequestStatus> {
-    protected  String requestId = null;
+  public static class RequestStatus extends CollectionAdminRequest<RequestStatusResponse> {
+
+    protected String requestId = null;
 
     public RequestStatus() {
-      action = CollectionAction.REQUESTSTATUS;
+      super(CollectionAction.REQUESTSTATUS);
     }
 
     public RequestStatus setRequestId(String requestId) {
@@ -603,23 +715,41 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = (ModifiableSolrParams) super.getParams();
+      if (requestId == null)
+        throw new IllegalArgumentException("You must call setRequestId() on this request");
       params.set(CoreAdminParams.REQUESTID, requestId);
       return params;
     }
 
     @Override
-    protected RequestStatus getThis() {
-      return this;
+    protected RequestStatusResponse createResponse(SolrClient client) {
+      return new RequestStatusResponse();
+    }
+
+    public RequestStatusState waitFor(SolrClient client, long timeoutSeconds)
+        throws IOException, SolrServerException, InterruptedException {
+      long finishTime = System.nanoTime() + TimeUnit.SECONDS.toNanos(timeoutSeconds);
+      RequestStatusState state = RequestStatusState.NOT_FOUND;
+      while (System.nanoTime() < finishTime) {
+        state = this.process(client).getRequestStatus();
+        if (state == RequestStatusState.COMPLETED || state == RequestStatusState.FAILED) {
+          new DeleteStatus().setRequestId(requestId).process(client);
+          return state;
+        }
+        TimeUnit.SECONDS.sleep(1);
+      }
+      return state;
     }
   }
 
   // DELETESTATUS request
-  public static class DeleteStatus extends CollectionAdminRequest<DeleteStatus> {
+  public static class DeleteStatus extends CollectionAdminRequest<CollectionAdminResponse> {
+
     protected String requestId = null;
     protected Boolean flush = null;
 
     public DeleteStatus() {
-      action = CollectionAction.DELETESTATUS;
+      super(CollectionAction.DELETESTATUS);
     }
 
     public DeleteStatus setRequestId(String requestId) {
@@ -652,18 +782,20 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     }
 
     @Override
-    protected DeleteStatus getThis() {
-      return this;
+    protected CollectionAdminResponse createResponse(SolrClient client) {
+      return new CollectionAdminResponse();
     }
+
   }
 
   // CREATEALIAS request
-  public static class CreateAlias extends AsyncCollectionAdminRequest<CreateAlias> {
+  public static class CreateAlias extends AsyncCollectionAdminRequest {
+
     protected String aliasName;
     protected String aliasedCollections;
 
     public CreateAlias() {
-      action = CollectionAction.CREATEALIAS;
+      super(CollectionAction.CREATEALIAS);
     }
 
     /**
@@ -696,6 +828,12 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     }
 
     @Override
+    public CreateAlias setAsyncId(String id) {
+      this.asyncId = id;
+      return this;
+    }
+
+    @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = (ModifiableSolrParams) super.getParams();
       params.set(CoreAdminParams.NAME, aliasName);
@@ -703,18 +841,15 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
       return params;
     }
 
-    @Override
-    protected CreateAlias getThis() {
-      return this;
-    }
   }
 
   // DELETEALIAS request
-  public static class DeleteAlias extends AsyncCollectionAdminRequest<DeleteAlias> {
+  public static class DeleteAlias extends AsyncCollectionAdminRequest {
+
     protected String aliasName;
 
     public DeleteAlias() {
-      action = CollectionAction.DELETEALIAS;
+      super(CollectionAction.DELETEALIAS);
     }
 
     public DeleteAlias setAliasName(String aliasName) {
@@ -723,20 +858,26 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     }
 
     @Override
+    public DeleteAlias setAsyncId(String id) {
+      this.asyncId = id;
+      return this;
+    }
+
+    @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
       params.set(CoreAdminParams.NAME, aliasName);
       return params;
     }
 
-    @Override
-    protected DeleteAlias getThis() {
-      return this;
-    }
+
   }
 
   // ADDREPLICA request
-  public static class AddReplica extends CollectionShardAsyncAdminRequest<AddReplica> {
+  public static class AddReplica extends AsyncCollectionAdminRequest {
+
+    protected String collection;
+    protected String shard;
     protected String node;
     protected String routeKey;
     protected String instanceDir;
@@ -744,7 +885,7 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     protected Properties properties;
 
     public AddReplica() {
-      action = CollectionAction.ADDREPLICA;
+      super(CollectionAction.ADDREPLICA);
     }
 
     public Properties getProperties() {
@@ -792,16 +933,37 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
       return this;
     }
 
+    public AddReplica setCollectionName(String collection) {
+      this.collection = collection;
+      return this;
+    }
+
+    public AddReplica setShardName(String shard) {
+      this.shard = shard;
+      return this;
+    }
+
+    @Override
+    public AddReplica setAsyncId(String id) {
+      this.asyncId = id;
+      return this;
+    }
+
     @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
-      if (shardName == null || shardName.isEmpty()) {
-        params.remove(CoreAdminParams.SHARD);
+      if (collection == null)
+        throw new IllegalArgumentException("You must call setCollection() on this request");
+      params.add(CoreAdminParams.COLLECTION, collection);
+      if (shard == null || shard.isEmpty()) {
         if (routeKey == null) {
           throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Either shard or routeKey must be provided");
         }
         params.add(ShardParams._ROUTE_, routeKey);
       }
+      else {
+        params.add(CoreAdminParams.SHARD, shard);
+      }
       if (node != null) {
         params.add("node", node);
       }
@@ -817,14 +979,12 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
       return params;
     }
 
-    @Override
-    protected AddReplica getThis() {
-      return this;
-    }
+
   }
 
   // DELETEREPLICA request
-  public static class DeleteReplica extends CollectionShardAsyncAdminRequest<DeleteReplica> {
+  public static class DeleteReplica extends AsyncShardSpecificAdminRequest {
+
     protected String replica;
     protected Boolean onlyIfDown;
     private Boolean deleteDataDir;
@@ -832,7 +992,7 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     private Boolean deleteIndexDir;
 
     public DeleteReplica() {
-      action = CollectionAction.DELETEREPLICA;
+      super(CollectionAction.DELETEREPLICA);
     }
 
     public DeleteReplica setReplica(String replica) {
@@ -854,6 +1014,24 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     }
 
     @Override
+    public DeleteReplica setCollectionName(String collection) {
+      this.collection = collection;
+      return this;
+    }
+
+    @Override
+    public DeleteReplica setShardName(String shard) {
+      this.shard = shard;
+      return this;
+    }
+
+    @Override
+    public DeleteReplica setAsyncId(String id) {
+      this.asyncId = id;
+      return this;
+    }
+
+    @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
       params.set(ZkStateReader.REPLICA_PROP, this.replica);
@@ -873,11 +1051,6 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
       return params;
     }
 
-    @Override
-    protected DeleteReplica getThis() {
-      return this;
-    }
-
     public Boolean getDeleteDataDir() {
       return deleteDataDir;
     }
@@ -898,12 +1071,13 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
   }
 
   // CLUSTERPROP request
-  public static class ClusterProp extends CollectionAdminRequest<ClusterProp> {
+  public static class ClusterProp extends CollectionAdminRequest<CollectionAdminResponse> {
+
     private String propertyName;
     private String propertyValue;
 
     public ClusterProp() {
-      this.action = CollectionAction.CLUSTERPROP;
+      super(CollectionAction.CLUSTERPROP);
     }
 
     public ClusterProp setPropertyName(String propertyName) {
@@ -934,13 +1108,16 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     }
 
     @Override
-    protected ClusterProp getThis() {
-      return this;
+    protected CollectionAdminResponse createResponse(SolrClient client) {
+      return new CollectionAdminResponse();
     }
+
+
   }
 
   // MIGRATE request
-  public static class Migrate extends AsyncCollectionAdminRequest<Migrate> {
+  public static class Migrate extends AsyncCollectionAdminRequest {
+
     private String collection;
     private String targetCollection;
     private String splitKey;
@@ -948,7 +1125,7 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     private Properties properties;
 
     public Migrate() {
-      action = CollectionAction.MIGRATE;
+      super(CollectionAction.MIGRATE);
     }
 
     public Migrate setCollectionName(String collection) {
@@ -997,6 +1174,12 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     }
 
     @Override
+    public Migrate setAsyncId(String id) {
+      this.asyncId = id;
+      return this;
+    }
+
+    @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
       params.set(CoreAdminParams.COLLECTION, collection);
@@ -1012,58 +1195,72 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
       return params;
     }
 
-    @Override
-    protected Migrate getThis() {
-      return this;
-    }
+
   }
 
   // ADDROLE request
-  public static class AddRole extends CollectionAdminRoleRequest<AddRole> {
+  public static class AddRole extends CollectionAdminRoleRequest {
+
     public AddRole() {
-      action = CollectionAction.ADDROLE;
+      super(CollectionAction.ADDROLE);
     }
 
     @Override
-    protected AddRole getThis() {
+    public AddRole setNode(String node) {
+      this.node = node;
+      return this;
+    }
+
+    @Override
+    public AddRole setRole(String role) {
+      this.role = role;
       return this;
     }
   }
 
   // REMOVEROLE request
-  public static class RemoveRole extends CollectionAdminRoleRequest<RemoveRole> {
+  public static class RemoveRole extends CollectionAdminRoleRequest {
+
     public RemoveRole() {
-      action = CollectionAction.REMOVEROLE;
+      super(CollectionAction.REMOVEROLE);
     }
 
     @Override
-    protected RemoveRole getThis() {
+    public RemoveRole setNode(String node) {
+      this.node = node;
+      return this;
+    }
+
+    @Override
+    public RemoveRole setRole(String role) {
+      this.role = role;
       return this;
     }
   }
 
   // OVERSEERSTATUS request
-  public static class OverseerStatus extends AsyncCollectionAdminRequest<OverseerStatus> {
+  public static class OverseerStatus extends AsyncCollectionAdminRequest {
 
     public OverseerStatus () {
-      action = CollectionAction.OVERSEERSTATUS;
+      super(CollectionAction.OVERSEERSTATUS);
     }
 
     @Override
-    protected OverseerStatus getThis() {
+    public OverseerStatus setAsyncId(String id) {
+      this.asyncId = id;
       return this;
     }
   }
 
   // CLUSTERSTATUS request
-  public static class ClusterStatus extends CollectionAdminRequest<ClusterStatus> {
+  public static class ClusterStatus extends CollectionAdminRequest<CollectionAdminResponse> {
 
     protected String shardName = null;
     protected String collection = null;
     protected String routeKey = null;
 
     public ClusterStatus () {
-      action = CollectionAction.CLUSTERSTATUS;
+      super(CollectionAction.CLUSTERSTATUS);
     }
 
     public ClusterStatus setCollectionName(String collectionName) {
@@ -1109,32 +1306,35 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     }
 
     @Override
-    protected ClusterStatus getThis() {
-      return this;
+    protected CollectionAdminResponse createResponse(SolrClient client) {
+      return new CollectionAdminResponse();
     }
+
+
   }
 
   // LIST request
-  public static class List extends CollectionAdminRequest<List> {
+  public static class List extends CollectionAdminRequest<CollectionAdminResponse> {
     public List () {
-      action = CollectionAction.LIST;
+      super(CollectionAction.LIST);
     }
 
     @Override
-    protected List getThis() {
-      return this;
+    protected CollectionAdminResponse createResponse(SolrClient client) {
+      return new CollectionAdminResponse();
     }
   }
 
   // ADDREPLICAPROP request
-  public static class AddReplicaProp extends CollectionShardAsyncAdminRequest<AddReplicaProp> {
+  public static class AddReplicaProp extends AsyncShardSpecificAdminRequest {
+
     private String replica;
     private String propertyName;
     private String propertyValue;
     private Boolean shardUnique;
 
     public AddReplicaProp() {
-      action = CollectionAction.ADDREPLICAPROP;
+      super(CollectionAction.ADDREPLICAPROP);
     }
 
     public String getReplica() {
@@ -1174,6 +1374,24 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     }
 
     @Override
+    public AddReplicaProp setCollectionName(String collection) {
+      this.collection = collection;
+      return this;
+    }
+
+    @Override
+    public AddReplicaProp setShardName(String shard) {
+      this.shard = shard;
+      return this;
+    }
+
+    @Override
+    public AddReplicaProp setAsyncId(String id) {
+      this.asyncId = id;
+      return this;
+    }
+
+    @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
       params.set(CoreAdminParams.REPLICA, replica);
@@ -1187,19 +1405,16 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
       return params;
     }
 
-    @Override
-    protected AddReplicaProp getThis() {
-      return this;
-    }
   }
 
   // DELETEREPLICAPROP request
-  public static class DeleteReplicaProp extends CollectionShardAsyncAdminRequest<DeleteReplicaProp> {
+  public static class DeleteReplicaProp extends AsyncShardSpecificAdminRequest {
+
     private String replica;
     private String propertyName;
 
     public DeleteReplicaProp() {
-      this.action = CollectionAction.DELETEREPLICAPROP;
+      super(CollectionAction.DELETEREPLICAPROP);
     }
 
     public String getReplica() {
@@ -1221,6 +1436,24 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     }
 
     @Override
+    public DeleteReplicaProp setCollectionName(String collection) {
+      this.collection = collection;
+      return this;
+    }
+
+    @Override
+    public DeleteReplicaProp setShardName(String shard) {
+      this.shard = shard;
+      return this;
+    }
+
+    @Override
+    public DeleteReplicaProp setAsyncId(String id) {
+      this.asyncId = id;
+      return this;
+    }
+
+    @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
       params.set("replica", replica);
@@ -1228,44 +1461,49 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
       return params;
     }
 
-    @Override
-    protected DeleteReplicaProp getThis() {
-      return this;
-    }
+
   }
 
   // MIGRATECLUSTERSTATE request
-  public static class MigrateClusterState extends CollectionShardAsyncAdminRequest<MigrateClusterState> {
+  public static class MigrateClusterState extends AsyncCollectionAdminRequest {
+
+    protected String collection;
 
     public MigrateClusterState() {
-      this.action = CollectionAction.MIGRATESTATEFORMAT;
+      super(CollectionAction.MIGRATESTATEFORMAT);
     }
 
-    @Override
-    public MigrateClusterState setShardName(String shard) {
-      throw new UnsupportedOperationException();
+    public MigrateClusterState setCollectionName(String collection) {
+      this.collection = collection;
+      return this;
     }
 
     @Override
-    public String getShardName() {
-      throw new UnsupportedOperationException();
+    public MigrateClusterState setAsyncId(String id) {
+      this.asyncId = id;
+      return this;
     }
 
     @Override
-    protected MigrateClusterState getThis() {
-      return this;
+    public SolrParams getParams() {
+      ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
+      if (collection == null)
+        throw new IllegalArgumentException("You must call setCollection() on this request");
+      params.set(CoreAdminParams.COLLECTION, collection);
+      return params;
     }
   }
 
   // BALANCESHARDUNIQUE request
-  public static class BalanceShardUnique extends AsyncCollectionAdminRequest<BalanceShardUnique> {
+  public static class BalanceShardUnique extends AsyncCollectionAdminRequest {
+
     protected String collection;
     protected String propertyName;
     protected Boolean onlyActiveNodes;
     protected Boolean shardUnique;
 
     public BalanceShardUnique() {
-      this.action = CollectionAction.BALANCESHARDUNIQUE;
+      super(CollectionAction.BALANCESHARDUNIQUE);
     }
 
     public String getPropertyName() {
@@ -1305,20 +1543,23 @@ public abstract class CollectionAdminRequest <Q extends CollectionAdminRequest<Q
     }
 
     @Override
+    public BalanceShardUnique setAsyncId(String id) {
+      this.asyncId = id;
+      return this;
+    }
+
+    @Override
     public SolrParams getParams() {
       ModifiableSolrParams params = new ModifiableSolrParams(super.getParams());
       params.set(CoreAdminParams.COLLECTION, collection);
       params.set("property", propertyName);
-      if(onlyActiveNodes != null)
+      if (onlyActiveNodes != null)
         params.set("onlyactivenodes", onlyActiveNodes);
-      if(shardUnique != null)
+      if (shardUnique != null)
         params.set("shardUnique", shardUnique);
       return params;
     }
 
-    @Override
-    protected BalanceShardUnique getThis() {
-      return this;
-    }
   }
+
 }


[29/50] [abbrv] lucene-solr git commit: SOLR-8736: schema GET operations on fields, dynamicFields, fieldTypes, copyField have less details

Posted by no...@apache.org.
SOLR-8736: schema GET operations on fields, dynamicFields, fieldTypes, copyField have less details


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

Branch: refs/heads/apiv2
Commit: 5ea6ee7362d5020d6a0b80f9c0efcb83b7bee196
Parents: bfd58bc
Author: Noble Paul <no...@apache.org>
Authored: Tue Mar 8 18:00:12 2016 +0530
Committer: Noble Paul <no...@apache.org>
Committed: Tue Mar 8 18:00:12 2016 +0530

----------------------------------------------------------------------
 solr/CHANGES.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5ea6ee73/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index b71c63b..4a14786 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -109,7 +109,8 @@ Upgrading from Solr 5.x
 
 * When requesting stats in date fields, "sum" is now a double value instead of a date. See SOLR-8671
 
-* SOLR-8736: The deprecated GET methods for schema are now accessible and implemented differently
+* SOLR-8736: The deprecated GET methods for schema are now accessible through the bulk API. The output
+  has less details and is not backward compatible.
 
 Detailed Change List
 ----------------------


[44/50] [abbrv] lucene-solr git commit: SOLR-8799: Improve error message when tuple can't be read by SolrJ JDBC

Posted by no...@apache.org.
SOLR-8799: Improve error message when tuple can't be read by SolrJ JDBC


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

Branch: refs/heads/apiv2
Commit: 56ad6e5d8a3d92f7ea496c598c2097aa572263cc
Parents: 4384627
Author: jbernste <jb...@apache.org>
Authored: Tue Mar 8 15:21:19 2016 -0500
Committer: jbernste <jb...@apache.org>
Committed: Tue Mar 8 15:22:42 2016 -0500

----------------------------------------------------------------------
 .../solr/client/solrj/io/sql/ResultSetImpl.java      |  2 +-
 .../apache/solr/client/solrj/io/sql/JdbcTest.java    | 15 +++++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/56ad6e5d/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/ResultSetImpl.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/ResultSetImpl.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/ResultSetImpl.java
index e2f8cf0..0aa3a4b 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/ResultSetImpl.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/ResultSetImpl.java
@@ -78,7 +78,7 @@ class ResultSetImpl implements ResultSet {
       this.firstTuple = this.solrStream.read();
       this.solrStream.pushBack(firstTuple);
     } catch (IOException e) {
-      throw new SQLException("Couldn't read first tuple", e);
+      throw new SQLException(e);
     }
 
     this.resultSetMetaData = new ResultSetMetaDataImpl(this);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/56ad6e5d/solr/solrj/src/test/org/apache/solr/client/solrj/io/sql/JdbcTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/io/sql/JdbcTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/io/sql/JdbcTest.java
index e1e9739..572491e 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/io/sql/JdbcTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/io/sql/JdbcTest.java
@@ -396,6 +396,21 @@ public class JdbcTest extends AbstractFullDistribZkTestBase {
       }
     }
 
+
+    //Test error propagation
+    props = new Properties();
+    props.put("aggregationMode", "facet");
+    try (Connection con = DriverManager.getConnection("jdbc:solr://" + zkHost + "?collection=collection1", props)) {
+      try (Statement stmt = con.createStatement()) {
+        try (ResultSet rs = stmt.executeQuery("select crap from collection1 group by a_s " +
+            "order by sum(a_f) desc")) {
+        } catch (Exception e) {
+          String errorMessage = e.getMessage();
+          assertTrue(errorMessage.contains("Group by queries must include atleast one aggregate function"));
+        }
+      }
+    }
+
     testDriverMetadata();
   }
 


[32/50] [abbrv] lucene-solr git commit: Merge remote-tracking branch 'origin/master'

Posted by no...@apache.org.
Merge remote-tracking branch 'origin/master'


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

Branch: refs/heads/apiv2
Commit: dd1dd46b8eca97e72207c402144d0d4ae0b08259
Parents: e70c638 862bf7b
Author: Noble Paul <no...@apache.org>
Authored: Tue Mar 8 18:54:20 2016 +0530
Committer: Noble Paul <no...@apache.org>
Committed: Tue Mar 8 18:54:20 2016 +0530

----------------------------------------------------------------------
 .../index/BaseStoredFieldsFormatTestCase.java   | 53 ++++++++------------
 1 file changed, 22 insertions(+), 31 deletions(-)
----------------------------------------------------------------------



[31/50] [abbrv] lucene-solr git commit: SOLR-8766: deprecated tag in solrconfig.xml is removed

Posted by no...@apache.org.
SOLR-8766: deprecated <admin> tag in solrconfig.xml is removed


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

Branch: refs/heads/apiv2
Commit: e70c638bcf5b2b76f3b2dd70fed55ccd6b25411d
Parents: 5ea6ee7
Author: Noble Paul <no...@apache.org>
Authored: Tue Mar 8 18:49:44 2016 +0530
Committer: Noble Paul <no...@apache.org>
Committed: Tue Mar 8 18:53:59 2016 +0530

----------------------------------------------------------------------
 solr/CHANGES.txt                                              | 2 ++
 .../src/test-files/solr/collection1/conf/solrconfig.xml       | 6 ------
 .../src/test-files/solr/minimr/conf/solrconfig.xml            | 6 ------
 .../src/test-files/solr/mrunit/conf/solrconfig.xml            | 7 -------
 .../solr/solrcelltest/collection1/conf/solrconfig.xml         | 6 ------
 .../src/test-files/solr/solrcloud/conf/solrconfig.xml         | 6 ------
 solr/example/example-DIH/solr/db/conf/solrconfig.xml          | 6 ------
 solr/example/example-DIH/solr/mail/conf/solrconfig.xml        | 6 ------
 solr/example/example-DIH/solr/rss/conf/solrconfig.xml         | 6 ------
 solr/example/example-DIH/solr/solr/conf/solrconfig.xml        | 6 ------
 solr/example/example-DIH/solr/tika/conf/solrconfig.xml        | 7 -------
 solr/example/files/conf/solrconfig.xml                        | 6 ------
 solr/server/solr/configsets/basic_configs/conf/solrconfig.xml | 5 -----
 .../configsets/data_driven_schema_configs/conf/solrconfig.xml | 7 -------
 .../sample_techproducts_configs/conf/solrconfig.xml           | 6 ------
 15 files changed, 2 insertions(+), 86 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e70c638b/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 4a14786..02021c5 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -405,6 +405,8 @@ Other Changes
 * SOLR-8736: schema GET operations on fields, dynamicFields, fieldTypes, copyField are
   reimplemented as a part of the bulk API with less details (noble)
 
+* SOLR-8766 : deprecated <admin> tag in solrconfig.xml is removed (noble)
+
 ==================  5.5.1 ==================
 
 Bug Fixes

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e70c638b/solr/contrib/morphlines-core/src/test-files/solr/collection1/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/morphlines-core/src/test-files/solr/collection1/conf/solrconfig.xml b/solr/contrib/morphlines-core/src/test-files/solr/collection1/conf/solrconfig.xml
index b8d1ca6..ab1acd9 100644
--- a/solr/contrib/morphlines-core/src/test-files/solr/collection1/conf/solrconfig.xml
+++ b/solr/contrib/morphlines-core/src/test-files/solr/collection1/conf/solrconfig.xml
@@ -1487,11 +1487,5 @@
       EditorialMarkerFactory will do exactly that:
      <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" />
     -->
-    
-
-  <!-- Legacy config for the admin interface -->
-  <admin>
-    <defaultQuery>*:*</defaultQuery>
-  </admin>
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e70c638b/solr/contrib/morphlines-core/src/test-files/solr/minimr/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/morphlines-core/src/test-files/solr/minimr/conf/solrconfig.xml b/solr/contrib/morphlines-core/src/test-files/solr/minimr/conf/solrconfig.xml
index 65637c1..f5ce41b 100644
--- a/solr/contrib/morphlines-core/src/test-files/solr/minimr/conf/solrconfig.xml
+++ b/solr/contrib/morphlines-core/src/test-files/solr/minimr/conf/solrconfig.xml
@@ -1508,10 +1508,4 @@
      <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" />
     -->
     
-
-  <!-- Legacy config for the admin interface -->
-  <admin>
-    <defaultQuery>*:*</defaultQuery>
-  </admin>
-
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e70c638b/solr/contrib/morphlines-core/src/test-files/solr/mrunit/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/morphlines-core/src/test-files/solr/mrunit/conf/solrconfig.xml b/solr/contrib/morphlines-core/src/test-files/solr/mrunit/conf/solrconfig.xml
index 691643f..d40b16d 100644
--- a/solr/contrib/morphlines-core/src/test-files/solr/mrunit/conf/solrconfig.xml
+++ b/solr/contrib/morphlines-core/src/test-files/solr/mrunit/conf/solrconfig.xml
@@ -1511,11 +1511,4 @@
       EditorialMarkerFactory will do exactly that:
      <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" />
     -->
-    
-
-  <!-- Legacy config for the admin interface -->
-  <admin>
-    <defaultQuery>*:*</defaultQuery>
-  </admin>
-
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e70c638b/solr/contrib/morphlines-core/src/test-files/solr/solrcelltest/collection1/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/morphlines-core/src/test-files/solr/solrcelltest/collection1/conf/solrconfig.xml b/solr/contrib/morphlines-core/src/test-files/solr/solrcelltest/collection1/conf/solrconfig.xml
index b8d1ca6..ab1acd9 100644
--- a/solr/contrib/morphlines-core/src/test-files/solr/solrcelltest/collection1/conf/solrconfig.xml
+++ b/solr/contrib/morphlines-core/src/test-files/solr/solrcelltest/collection1/conf/solrconfig.xml
@@ -1487,11 +1487,5 @@
       EditorialMarkerFactory will do exactly that:
      <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" />
     -->
-    
-
-  <!-- Legacy config for the admin interface -->
-  <admin>
-    <defaultQuery>*:*</defaultQuery>
-  </admin>
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e70c638b/solr/contrib/morphlines-core/src/test-files/solr/solrcloud/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/morphlines-core/src/test-files/solr/solrcloud/conf/solrconfig.xml b/solr/contrib/morphlines-core/src/test-files/solr/solrcloud/conf/solrconfig.xml
index 336c789..9d33201 100644
--- a/solr/contrib/morphlines-core/src/test-files/solr/solrcloud/conf/solrconfig.xml
+++ b/solr/contrib/morphlines-core/src/test-files/solr/solrcloud/conf/solrconfig.xml
@@ -1510,11 +1510,5 @@
       EditorialMarkerFactory will do exactly that:
      <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" />
     -->
-    
-
-  <!-- Legacy config for the admin interface -->
-  <admin>
-    <defaultQuery>*:*</defaultQuery>
-  </admin>
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e70c638b/solr/example/example-DIH/solr/db/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/example/example-DIH/solr/db/conf/solrconfig.xml b/solr/example/example-DIH/solr/db/conf/solrconfig.xml
index e541565..339e77f 100644
--- a/solr/example/example-DIH/solr/db/conf/solrconfig.xml
+++ b/solr/example/example-DIH/solr/db/conf/solrconfig.xml
@@ -1486,11 +1486,5 @@
       EditorialMarkerFactory will do exactly that:
      <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" />
     -->
-    
-
-  <!-- Legacy config for the admin interface -->
-  <admin>
-    <defaultQuery>*:*</defaultQuery>
-  </admin>
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e70c638b/solr/example/example-DIH/solr/mail/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/example/example-DIH/solr/mail/conf/solrconfig.xml b/solr/example/example-DIH/solr/mail/conf/solrconfig.xml
index 30c61a8..0698704 100644
--- a/solr/example/example-DIH/solr/mail/conf/solrconfig.xml
+++ b/solr/example/example-DIH/solr/mail/conf/solrconfig.xml
@@ -1489,11 +1489,5 @@
       EditorialMarkerFactory will do exactly that:
      <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" />
     -->
-    
-
-  <!-- Legacy config for the admin interface -->
-  <admin>
-    <defaultQuery>*:*</defaultQuery>
-  </admin>
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e70c638b/solr/example/example-DIH/solr/rss/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/example/example-DIH/solr/rss/conf/solrconfig.xml b/solr/example/example-DIH/solr/rss/conf/solrconfig.xml
index a6597a1..152321e 100644
--- a/solr/example/example-DIH/solr/rss/conf/solrconfig.xml
+++ b/solr/example/example-DIH/solr/rss/conf/solrconfig.xml
@@ -1485,11 +1485,5 @@
       EditorialMarkerFactory will do exactly that:
      <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" />
     -->
-    
-
-  <!-- Legacy config for the admin interface -->
-  <admin>
-    <defaultQuery>*:*</defaultQuery>
-  </admin>
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e70c638b/solr/example/example-DIH/solr/solr/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/example/example-DIH/solr/solr/conf/solrconfig.xml b/solr/example/example-DIH/solr/solr/conf/solrconfig.xml
index 84469d9..7091b9d 100644
--- a/solr/example/example-DIH/solr/solr/conf/solrconfig.xml
+++ b/solr/example/example-DIH/solr/solr/conf/solrconfig.xml
@@ -1485,11 +1485,5 @@
       EditorialMarkerFactory will do exactly that:
      <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" />
     -->
-    
-
-  <!-- Legacy config for the admin interface -->
-  <admin>
-    <defaultQuery>*:*</defaultQuery>
-  </admin>
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e70c638b/solr/example/example-DIH/solr/tika/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/example/example-DIH/solr/tika/conf/solrconfig.xml b/solr/example/example-DIH/solr/tika/conf/solrconfig.xml
index 9c770a0..c3d0168 100644
--- a/solr/example/example-DIH/solr/tika/conf/solrconfig.xml
+++ b/solr/example/example-DIH/solr/tika/conf/solrconfig.xml
@@ -1463,11 +1463,4 @@
       EditorialMarkerFactory will do exactly that:
      <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" />
     -->
-    
-
-  <!-- Legacy config for the admin interface -->
-  <admin>
-    <defaultQuery>*:*</defaultQuery>
-  </admin>
-
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e70c638b/solr/example/files/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/example/files/conf/solrconfig.xml b/solr/example/files/conf/solrconfig.xml
index 4dea6c9..cab776a 100644
--- a/solr/example/files/conf/solrconfig.xml
+++ b/solr/example/files/conf/solrconfig.xml
@@ -1505,10 +1505,4 @@
      <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" />
     -->
 
-
-  <!-- Legacy config for the admin interface -->
-  <admin>
-    <defaultQuery>*:*</defaultQuery>
-  </admin>
-
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e70c638b/solr/server/solr/configsets/basic_configs/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/server/solr/configsets/basic_configs/conf/solrconfig.xml b/solr/server/solr/configsets/basic_configs/conf/solrconfig.xml
index 6b2f745..9ee1ff5 100644
--- a/solr/server/solr/configsets/basic_configs/conf/solrconfig.xml
+++ b/solr/server/solr/configsets/basic_configs/conf/solrconfig.xml
@@ -559,9 +559,4 @@
     </arr>
   </requestHandler>
 
-  <!-- Legacy config for the admin interface -->
-  <admin>
-    <defaultQuery>*:*</defaultQuery>
-  </admin>
-
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e70c638b/solr/server/solr/configsets/data_driven_schema_configs/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/server/solr/configsets/data_driven_schema_configs/conf/solrconfig.xml b/solr/server/solr/configsets/data_driven_schema_configs/conf/solrconfig.xml
index 72d7bdf..6d9c8b5 100644
--- a/solr/server/solr/configsets/data_driven_schema_configs/conf/solrconfig.xml
+++ b/solr/server/solr/configsets/data_driven_schema_configs/conf/solrconfig.xml
@@ -1479,11 +1479,4 @@
       EditorialMarkerFactory will do exactly that:
      <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" />
     -->
-
-
-  <!-- Legacy config for the admin interface -->
-  <admin>
-    <defaultQuery>*:*</defaultQuery>
-  </admin>
-
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e70c638b/solr/server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml b/solr/server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml
index 900a123..c8f52a6 100644
--- a/solr/server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml
+++ b/solr/server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml
@@ -1698,10 +1698,4 @@
      <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" />
     -->
     
-
-  <!-- Legacy config for the admin interface -->
-  <admin>
-    <defaultQuery>*:*</defaultQuery>
-  </admin>
-
 </config>


[24/50] [abbrv] lucene-solr git commit: SOLR-6926: Remove deprecated "ant example"; replaced by "ant server" a year ago

Posted by no...@apache.org.
SOLR-6926: Remove deprecated "ant example"; replaced by "ant server" a year ago


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

Branch: refs/heads/apiv2
Commit: a0a571caa9777a8a6401b88ff9c4d2bb982055b8
Parents: f7f81c3
Author: David Smiley <ds...@apache.org>
Authored: Mon Mar 7 23:48:31 2016 -0500
Committer: David Smiley <ds...@apache.org>
Committed: Mon Mar 7 23:48:31 2016 -0500

----------------------------------------------------------------------
 solr/build.xml | 14 --------------
 1 file changed, 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a0a571ca/solr/build.xml
----------------------------------------------------------------------
diff --git a/solr/build.xml b/solr/build.xml
index 218bf8c..61503df 100644
--- a/solr/build.xml
+++ b/solr/build.xml
@@ -809,18 +809,4 @@
     <contrib-crawl target="-append-module-dependencies-properties"/>
   </target>
 
-  <target name="example" depends="server">
-    <!-- no description so -p doesn't list it -->
-    <echo>
-
-    ! ! ! NOTICE NOTICE NOTICE ! ! !
-
-    'ant example' is no longer recomended
-
-    Use 'ant server' instead
-
-    'ant example' is going to be removed at some point
-
-    </echo>
-  </target>
 </project>


[03/50] [abbrv] lucene-solr git commit: SOLR-8736: schema GET operations on fields, dynamicFields, fieldTypes, copyField are reimplemented as a part of the bulk API with less details. The tests and write implementations are removed

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
index acc8c13..4319c3e 100644
--- a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
+++ b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
@@ -39,6 +39,7 @@ import org.apache.lucene.uninverting.UninvertingReader;
 import org.apache.lucene.util.Version;
 import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.common.SolrException;
+import org.apache.solr.common.params.MapSolrParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.NamedList;
@@ -1352,6 +1353,10 @@ public class IndexSchema {
    * Get a map of property name -&gt; value for the whole schema.
    */
   public SimpleOrderedMap<Object> getNamedPropertyValues() {
+    return getNamedPropertyValues(new MapSolrParams(Collections.EMPTY_MAP));
+
+  }
+  public SimpleOrderedMap<Object> getNamedPropertyValues(SolrParams params) {
     SimpleOrderedMap<Object> topLevel = new SimpleOrderedMap<>();
     topLevel.add(NAME, getSchemaName());
     topLevel.add(VERSION, getVersion());
@@ -1372,19 +1377,19 @@ public class IndexSchema {
     List<SimpleOrderedMap<Object>> fieldTypeProperties = new ArrayList<>();
     SortedMap<String,FieldType> sortedFieldTypes = new TreeMap<>(fieldTypes);
     for (FieldType fieldType : sortedFieldTypes.values()) {
-      fieldTypeProperties.add(fieldType.getNamedPropertyValues(false));
+      fieldTypeProperties.add(fieldType.getNamedPropertyValues(params.getBool("showDefaults", false)));
     }
     topLevel.add(FIELD_TYPES, fieldTypeProperties);  
     List<SimpleOrderedMap<Object>> fieldProperties = new ArrayList<>();
     SortedSet<String> fieldNames = new TreeSet<>(fields.keySet());
     for (String fieldName : fieldNames) {
-      fieldProperties.add(fields.get(fieldName).getNamedPropertyValues(false));
+      fieldProperties.add(fields.get(fieldName).getNamedPropertyValues(params.getBool("showDefaults", false)));
     }
     topLevel.add(FIELDS, fieldProperties);
     List<SimpleOrderedMap<Object>> dynamicFieldProperties = new ArrayList<>();
     for (IndexSchema.DynamicField dynamicField : dynamicFields) {
       if ( ! dynamicField.getRegex().startsWith(INTERNAL_POLY_FIELD_PREFIX)) { // omit internal polyfields
-        dynamicFieldProperties.add(dynamicField.getPrototype().getNamedPropertyValues(false));
+        dynamicFieldProperties.add(dynamicField.getPrototype().getNamedPropertyValues(params.getBool("showDefaults", false)));
       }
     }
     topLevel.add(DYNAMIC_FIELDS, dynamicFieldProperties);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
index d87eb69..f291b2f 100644
--- a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
+++ b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
@@ -35,10 +35,12 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Random;
 import java.util.Set;
 
+import com.google.common.collect.ImmutableSet;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.http.Header;
@@ -84,6 +86,7 @@ import org.apache.solr.request.SolrRequestInfo;
 import org.apache.solr.response.QueryResponseWriter;
 import org.apache.solr.response.QueryResponseWriterUtil;
 import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.schema.IndexSchema;
 import org.apache.solr.security.AuthenticationPlugin;
 import org.apache.solr.security.AuthorizationContext;
 import org.apache.solr.security.AuthorizationContext.CollectionRequest;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/rest/schema/TestClassNameShortening.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestClassNameShortening.java b/solr/core/src/test/org/apache/solr/rest/schema/TestClassNameShortening.java
index ddbd331..52ba10b 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestClassNameShortening.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/TestClassNameShortening.java
@@ -18,13 +18,14 @@ package org.apache.solr.rest.schema;
 import org.apache.solr.util.RestTestBase;
 import org.eclipse.jetty.servlet.ServletHolder;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.restlet.ext.servlet.ServerServlet;
 
 import java.util.SortedMap;
 import java.util.TreeMap;
 
-
+@Ignore
 public class TestClassNameShortening extends RestTestBase {
 
   @BeforeClass

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/rest/schema/TestCopyFieldCollectionResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestCopyFieldCollectionResource.java b/solr/core/src/test/org/apache/solr/rest/schema/TestCopyFieldCollectionResource.java
index 5eeee8c..c0f936d 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestCopyFieldCollectionResource.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/TestCopyFieldCollectionResource.java
@@ -30,73 +30,51 @@ public class TestCopyFieldCollectionResource extends SolrRestletTestBase {
            +"                                      and int[@name='maxChars'][.='200']]",
 
             "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='title']"
-           +"                                      and str[@name='dest'][.='dest_sub_no_ast_s']"
-           +"                                      and str[@name='destDynamicBase'][.='*_s']]",
+           +"                                      and str[@name='dest'][.='dest_sub_no_ast_s']]",
 
-            "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='*_i']"
+        "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='*_i']"
            +"                                      and str[@name='dest'][.='title']]",
 
             "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='*_i']"
            +"                                      and str[@name='dest'][.='*_s']]",
 
             "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='*_i']"
-           +"                                      and str[@name='dest'][.='*_dest_sub_s']"
-           +"                                      and str[@name='destDynamicBase'][.='*_s']]",
+           +"                                      and str[@name='dest'][.='*_dest_sub_s']]",
 
-            "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='*_i']"
-           +"                                      and str[@name='dest'][.='dest_sub_no_ast_s']"
-           +"                                      and str[@name='destDynamicBase'][.='*_s']]",
+        "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='*_i']"
+           +"                                      and str[@name='dest'][.='dest_sub_no_ast_s']]",
 
             "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='*_src_sub_i']"
-           +"                                      and str[@name='sourceDynamicBase'][.='*_i']"
            +"                                      and str[@name='dest'][.='title']]",
 
             "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='*_src_sub_i']"
-           +"                                      and str[@name='sourceDynamicBase'][.='*_i']"
            +"                                      and str[@name='dest'][.='*_s']]",
 
             "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='*_src_sub_i']"
-           +"                                      and str[@name='sourceDynamicBase'][.='*_i']"
-           +"                                      and str[@name='dest'][.='*_dest_sub_s']"
-           +"                                      and str[@name='destDynamicBase'][.='*_s']]",
+           +"                                      and str[@name='dest'][.='*_dest_sub_s']]",
 
-            "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='*_src_sub_i']"
-           +"                                      and str[@name='sourceDynamicBase'][.='*_i']"
-           +"                                      and str[@name='dest'][.='dest_sub_no_ast_s']"
-           +"                                      and str[@name='destDynamicBase'][.='*_s']]",
+        "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='*_src_sub_i']"
+           +"                                      and str[@name='dest'][.='dest_sub_no_ast_s']]",
 
             "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='src_sub_no_ast_i']"
-           +"                                      and str[@name='sourceDynamicBase'][.='*_i']"
            +"                                      and str[@name='dest'][.='*_s']]",
 
             "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='src_sub_no_ast_i']"
-           +"                                      and str[@name='sourceDynamicBase'][.='*_i']"
-           +"                                      and str[@name='dest'][.='*_dest_sub_s']"
-           +"                                      and str[@name='destDynamicBase'][.='*_s']]",
+           +"                                      and str[@name='dest'][.='*_dest_sub_s']]",
 
             "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='src_sub_no_ast_i']"
-           +"                                      and str[@name='sourceDynamicBase'][.='*_i']"
-           +"                                      and str[@name='dest'][.='dest_sub_no_ast_s']"
-           +"                                      and str[@name='destDynamicBase'][.='*_s']]",
+           +"                                      and str[@name='dest'][.='dest_sub_no_ast_s']]",
 
             "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='title_*']"
-           +"                                      and arr[@name='sourceExplicitFields']/str[.='title_stemmed']"
-           +"                                      and arr[@name='sourceExplicitFields']/str[.='title_lettertok']"
            +"                                      and str[@name='dest'][.='text']]",
 
             "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='title_*']"
-           +"                                      and arr[@name='sourceExplicitFields']/str[.='title_stemmed']"
-           +"                                      and arr[@name='sourceExplicitFields']/str[.='title_lettertok']"
            +"                                      and str[@name='dest'][.='*_s']]",
 
             "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='title_*']"
-           +"                                      and arr[@name='sourceExplicitFields']/str[.='title_stemmed']"
-           +"                                      and arr[@name='sourceExplicitFields']/str[.='title_lettertok']"
            +"                                      and str[@name='dest'][.='*_dest_sub_s']]",
 
             "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='title_*']"
-           +"                                      and arr[@name='sourceExplicitFields']/str[.='title_stemmed']"
-           +"                                      and arr[@name='sourceExplicitFields']/str[.='title_lettertok']"
            +"                                      and str[@name='dest'][.='dest_sub_no_ast_s']]");
   }
 
@@ -104,56 +82,22 @@ public class TestCopyFieldCollectionResource extends SolrRestletTestBase {
   public void testJsonGetAllCopyFields() throws Exception {
     assertJQ("/schema/copyfields?indent=on&wt=json",
              "/copyFields/[1]=={'source':'src_sub_no_ast_i','dest':'title'}",
-             "/copyFields/[7]=={'source':'title','dest':'dest_sub_no_ast_s','destDynamicBase':'*_s'}",
+             "/copyFields/[7]=={'source':'title','dest':'dest_sub_no_ast_s'}",
 
              "/copyFields/[8]=={'source':'*_i','dest':'title'}",
              "/copyFields/[9]=={'source':'*_i','dest':'*_s'}",
-             "/copyFields/[10]=={'source':'*_i','dest':'*_dest_sub_s','destDynamicBase':'*_s'}",
-             "/copyFields/[11]=={'source':'*_i','dest':'dest_sub_no_ast_s','destDynamicBase':'*_s'}",
+             "/copyFields/[10]=={'source':'*_i','dest':'*_dest_sub_s'}",
+             "/copyFields/[11]=={'source':'*_i','dest':'dest_sub_no_ast_s'}",
 
-             "/copyFields/[12]=={'source':'*_src_sub_i','sourceDynamicBase':'*_i','dest':'title'}",
-             "/copyFields/[13]=={'source':'*_src_sub_i','sourceDynamicBase':'*_i','dest':'*_s'}",
-             "/copyFields/[14]=={'source':'*_src_sub_i','sourceDynamicBase':'*_i','dest':'*_dest_sub_s','destDynamicBase':'*_s'}",
-             "/copyFields/[15]=={'source':'*_src_sub_i','sourceDynamicBase':'*_i','dest':'dest_sub_no_ast_s','destDynamicBase':'*_s'}",
+             "/copyFields/[12]=={'source':'*_src_sub_i','dest':'title'}",
+             "/copyFields/[13]=={'source':'*_src_sub_i','dest':'*_s'}",
+             "/copyFields/[14]=={'source':'*_src_sub_i','dest':'*_dest_sub_s'}",
+             "/copyFields/[15]=={'source':'*_src_sub_i','dest':'dest_sub_no_ast_s'}",
 
-             "/copyFields/[16]=={'source':'src_sub_no_ast_i','sourceDynamicBase':'*_i','dest':'*_s'}",
-             "/copyFields/[17]=={'source':'src_sub_no_ast_i','sourceDynamicBase':'*_i','dest':'*_dest_sub_s','destDynamicBase':'*_s'}",
-             "/copyFields/[18]=={'source':'src_sub_no_ast_i','sourceDynamicBase':'*_i','dest':'dest_sub_no_ast_s','destDynamicBase':'*_s'}");
+             "/copyFields/[16]=={'source':'src_sub_no_ast_i','dest':'*_s'}",
+             "/copyFields/[17]=={'source':'src_sub_no_ast_i','dest':'*_dest_sub_s'}",
+             "/copyFields/[18]=={'source':'src_sub_no_ast_i','dest':'dest_sub_no_ast_s'}");
 
   }
 
-  @Test
-  public void testRestrictSource() throws Exception {
-    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=title,*_i,*_src_sub_i,src_sub_no_ast_i",
-            "count(/response/arr[@name='copyFields']/lst) = 16", // 4 + 4 + 4 + 4
-            "count(/response/arr[@name='copyFields']/lst/str[@name='source'][.='title']) = 4",
-            "count(/response/arr[@name='copyFields']/lst/str[@name='source'][.='*_i']) = 4",
-            "count(/response/arr[@name='copyFields']/lst/str[@name='source'][.='*_src_sub_i']) = 4",
-            "count(/response/arr[@name='copyFields']/lst/str[@name='source'][.='src_sub_no_ast_i']) = 4");
-  }
-
-  @Test
-  public void testRestrictDest() throws Exception {
-    assertQ("/schema/copyfields/?indent=on&wt=xml&dest.fl=title,*_s,*_dest_sub_s,dest_sub_no_ast_s",
-            "count(/response/arr[@name='copyFields']/lst) = 16", // 3 + 4 + 4 + 5
-            "count(/response/arr[@name='copyFields']/lst/str[@name='dest'][.='title']) = 3",
-            "count(/response/arr[@name='copyFields']/lst/str[@name='dest'][.='*_s']) = 4",
-            "count(/response/arr[@name='copyFields']/lst/str[@name='dest'][.='*_dest_sub_s']) = 4",
-            "count(/response/arr[@name='copyFields']/lst/str[@name='dest'][.='dest_sub_no_ast_s']) = 5");
-  }
-
-  @Test
-  public void testRestrictSourceAndDest() throws Exception {
-    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=title,*_i&dest.fl=title,dest_sub_no_ast_s",
-            "count(/response/arr[@name='copyFields']/lst) = 3",
-
-            "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='title']"
-           +"                                      and str[@name='dest'][.='dest_sub_no_ast_s']]",
-
-            "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='*_i']"
-           +"                                      and str[@name='dest'][.='title']]",
-
-            "/response/arr[@name='copyFields']/lst[    str[@name='source'][.='*_i']"
-           +"                                      and str[@name='dest'][.='dest_sub_no_ast_s']]");
-  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/rest/schema/TestDynamicFieldCollectionResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestDynamicFieldCollectionResource.java b/solr/core/src/test/org/apache/solr/rest/schema/TestDynamicFieldCollectionResource.java
index 318b28a..032bbad 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestDynamicFieldCollectionResource.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/TestDynamicFieldCollectionResource.java
@@ -30,39 +30,10 @@ public class TestDynamicFieldCollectionResource extends SolrRestletTestBase {
   }
 
   @Test
-  public void testGetTwoDynamicFields() throws IOException {
-    assertQ("/schema/dynamicfields?indent=on&wt=xml&fl=*_i,*_s",
-            "count(/response/arr[@name='dynamicFields']/lst/str[@name='name']) = 2",
-            "(/response/arr[@name='dynamicFields']/lst/str[@name='name'])[1] = '*_i'",
-            "(/response/arr[@name='dynamicFields']/lst/str[@name='name'])[2] = '*_s'");
-  }
-
-  @Test
-  public void testNotFoundDynamicFields() throws IOException {
-    assertQ("/schema/dynamicfields?indent=on&wt=xml&fl=*_not_in_there,this_one_isnt_either_*",
-            "count(/response/arr[@name='dynamicFields']) = 1",
-            "count(/response/arr[@name='dynamicfields']/lst/str[@name='name']) = 0");
-  }
-
-  @Test
   public void testJsonGetAllDynamicFields() throws Exception {
     assertJQ("/schema/dynamicfields?indent=on",
              "/dynamicFields/[0]/name=='*_coordinate'",
              "/dynamicFields/[1]/name=='ignored_*'",
              "/dynamicFields/[2]/name=='*_mfacet'");
   }
-  
-  @Test
-  public void testJsonGetTwoDynamicFields() throws Exception {
-    assertJQ("/schema/dynamicfields?indent=on&fl=*_i,*_s&wt=xml", // assertJQ will fix the wt param to be json
-             "/dynamicFields/[0]/name=='*_i'",
-             "/dynamicFields/[1]/name=='*_s'");
-  }
-
-  @Test
-  public void testJsonPostFieldsToNonMutableIndexSchema() throws Exception {
-    assertJPost("/schema/dynamicfields",
-        "[{\"name\":\"foobarbaz\", \"type\":\"text_general\", \"stored\":\"false\"}]",
-        "/error/msg=='This IndexSchema is not mutable.'");
-  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/rest/schema/TestDynamicFieldResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestDynamicFieldResource.java b/solr/core/src/test/org/apache/solr/rest/schema/TestDynamicFieldResource.java
index 54b17fc..7ca7953 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestDynamicFieldResource.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/TestDynamicFieldResource.java
@@ -67,11 +67,4 @@ public class TestDynamicFieldResource extends SolrRestletTestBase {
              "/dynamicField/required==false",
              "/dynamicField/tokenized==false");
   }
-
-  @Test
-  public void testJsonPutFieldToNonMutableIndexSchema() throws Exception {
-    assertJPut("/schema/dynamicfields/newfield_*",
-        "{\"type\":\"text_general\", \"stored\":\"false\"}",
-        "/error/msg=='This IndexSchema is not mutable.'");
-  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/rest/schema/TestFieldCollectionResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestFieldCollectionResource.java b/solr/core/src/test/org/apache/solr/rest/schema/TestFieldCollectionResource.java
index 571acc5..dd55415 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestFieldCollectionResource.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/TestFieldCollectionResource.java
@@ -30,45 +30,6 @@ public class TestFieldCollectionResource extends SolrRestletTestBase {
             "(/response/arr[@name='fields']/lst/str[@name='name'])[3] = '_version_'");
   }
 
-  @Test
-  public void testGetTwoFields() throws IOException {
-    assertQ("/schema/fields?indent=on&wt=xml&fl=id,_version_",
-            "count(/response/arr[@name='fields']/lst/str[@name='name']) = 2",
-            "(/response/arr[@name='fields']/lst/str[@name='name'])[1] = 'id'",
-            "(/response/arr[@name='fields']/lst/str[@name='name'])[2] = '_version_'");
-  }
-  
-  @Test
-  public void testGetThreeFieldsDontIncludeDynamic() throws IOException {
-    // 
-    assertQ("/schema/fields?indent=on&wt=xml&fl=id,_version_,price_i",
-            "count(/response/arr[@name='fields']/lst/str[@name='name']) = 2",
-            "(/response/arr[@name='fields']/lst/str[@name='name'])[1] = 'id'",
-            "(/response/arr[@name='fields']/lst/str[@name='name'])[2] = '_version_'");
-  }
-
-  @Test
-  public void testGetThreeFieldsIncludeDynamic() throws IOException {
-    assertQ("/schema/fields?indent=on&wt=xml&fl=id,_version_,price_i&includeDynamic=on",
-
-            "count(/response/arr[@name='fields']/lst/str[@name='name']) = 3",
-
-            "(/response/arr[@name='fields']/lst/str[@name='name'])[1] = 'id'",
-
-            "(/response/arr[@name='fields']/lst/str[@name='name'])[2] = '_version_'",
-
-            "(/response/arr[@name='fields']/lst/str[@name='name'])[3] = 'price_i'",
-
-            "/response/arr[@name='fields']/lst[    str[@name='name']='price_i'    "
-           +"                                  and str[@name='dynamicBase']='*_i']");
-  }
-
-  @Test
-  public void testNotFoundFields() throws IOException {
-    assertQ("/schema/fields?indent=on&wt=xml&fl=not_in_there,this_one_either",
-            "count(/response/arr[@name='fields']) = 1",
-            "count(/response/arr[@name='fields']/lst/str[@name='name']) = 0");
-  }
 
   @Test
   public void testJsonGetAllFields() throws Exception {
@@ -78,10 +39,4 @@ public class TestFieldCollectionResource extends SolrRestletTestBase {
              "/fields/[2]/name=='_version_'");
   }
 
-  @Test
-  public void testJsonGetTwoFields() throws Exception {
-    assertJQ("/schema/fields?indent=on&fl=id,_version_&wt=xml", // assertJQ should fix the wt param to be json
-             "/fields/[0]/name=='id'",
-             "/fields/[1]/name=='_version_'");
-  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/rest/schema/TestFieldResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestFieldResource.java b/solr/core/src/test/org/apache/solr/rest/schema/TestFieldResource.java
index 711e3c0..627aee0 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestFieldResource.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/TestFieldResource.java
@@ -72,18 +72,12 @@ public class TestFieldResource extends SolrRestletTestBase {
              "/field/tokenized==true");
   }
   
-  @Test
-  public void testGetFieldIncludeDynamic() throws Exception {
-    assertQ("/schema/fields/some_crazy_name_i?indent=on&wt=xml&includeDynamic=true",
-            "/response/lst[@name='field']/str[@name='name'] = 'some_crazy_name_i'",
-            "/response/lst[@name='field']/str[@name='dynamicBase'] = '*_i'");    
-  }
-  
+
   @Test
   public void testGetFieldDontShowDefaults() throws Exception {
     String[] tests = { 
         "count(/response/lst[@name='field']) = 1",
-        "count(/response/lst[@name='field']/*) = 7",
+        "count(/response/lst[@name='field']/*) = 6",
         "/response/lst[@name='field']/str[@name='name'] = 'id'",
         "/response/lst[@name='field']/str[@name='type'] = 'string'",
         "/response/lst[@name='field']/bool[@name='indexed'] = 'true'",
@@ -95,17 +89,4 @@ public class TestFieldResource extends SolrRestletTestBase {
     assertQ("/schema/fields/id?indent=on&wt=xml&showDefaults=false", tests);
   }
   
-  @Test
-  public void testJsonPutFieldToNonMutableIndexSchema() throws Exception {
-    assertJPut("/schema/fields/newfield",
-        "{\"type\":\"text_general\", \"stored\":\"false\"}",
-        "/error/msg=='This IndexSchema is not mutable.'");
-  }
-
-  @Test
-  public void testJsonPostFieldsToNonMutableIndexSchema() throws Exception {
-    assertJPost("/schema/fields",
-        "[{\"name\":\"foobarbaz\", \"type\":\"text_general\", \"stored\":\"false\"}]",
-        "/error/msg=='This IndexSchema is not mutable.'");
-  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/rest/schema/TestFieldTypeCollectionResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestFieldTypeCollectionResource.java b/solr/core/src/test/org/apache/solr/rest/schema/TestFieldTypeCollectionResource.java
index a61f644..53cd1c0 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestFieldTypeCollectionResource.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/TestFieldTypeCollectionResource.java
@@ -19,6 +19,7 @@ import org.apache.solr.rest.SolrRestletTestBase;
 import org.junit.Test;
 
 public class TestFieldTypeCollectionResource extends SolrRestletTestBase {
+
   @Test
   public void testGetAllFieldTypes() throws Exception {
     assertQ("/schema/fieldtypes?indent=on&wt=xml",

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/rest/schema/TestFieldTypeResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestFieldTypeResource.java b/solr/core/src/test/org/apache/solr/rest/schema/TestFieldTypeResource.java
index 2f0c241..eb72aed 100644
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestFieldTypeResource.java
+++ b/solr/core/src/test/org/apache/solr/rest/schema/TestFieldTypeResource.java
@@ -24,7 +24,7 @@ public class TestFieldTypeResource extends SolrRestletTestBase {
   public void testGetFieldType() throws Exception {
     assertQ("/schema/fieldtypes/float?indent=on&wt=xml&showDefaults=true",
             "count(/response/lst[@name='fieldType']) = 1",
-            "count(/response/lst[@name='fieldType']/*) = 18",
+            "count(/response/lst[@name='fieldType']/*) = 16",
             "/response/lst[@name='fieldType']/str[@name='name'] = 'float'",
             "/response/lst[@name='fieldType']/str[@name='class'] = 'solr.TrieFloatField'",
             "/response/lst[@name='fieldType']/str[@name='precisionStep'] ='0'",
@@ -39,9 +39,7 @@ public class TestFieldTypeResource extends SolrRestletTestBase {
             "/response/lst[@name='fieldType']/bool[@name='omitPositions'] = 'false'",
             "/response/lst[@name='fieldType']/bool[@name='storeOffsetsWithPositions'] = 'false'",
             "/response/lst[@name='fieldType']/bool[@name='multiValued'] = 'false'",
-            "/response/lst[@name='fieldType']/bool[@name='tokenized'] = 'false'",
-            "/response/lst[@name='fieldType']/arr[@name='fields']/str = 'weight'",
-            "/response/lst[@name='fieldType']/arr[@name='dynamicFields']/str = '*_f'");
+            "/response/lst[@name='fieldType']/bool[@name='tokenized'] = 'false'");
   }
 
   @Test
@@ -69,22 +67,19 @@ public class TestFieldTypeResource extends SolrRestletTestBase {
              "/fieldType/omitPositions==false",
              "/fieldType/storeOffsetsWithPositions==false",
              "/fieldType/multiValued==false",
-             "/fieldType/tokenized==false",
-             "/fieldType/fields==['weight']",
-             "/fieldType/dynamicFields==['*_f']");
+             "/fieldType/tokenized==false");
   }
   
   @Test
   public void testGetFieldTypeDontShowDefaults() throws Exception {
     assertQ("/schema/fieldtypes/teststop?wt=xml&indent=on",
-            "count(/response/lst[@name='fieldType']/*) = 5",
+            "count(/response/lst[@name='fieldType']/*) = 3",
             "/response/lst[@name='fieldType']/str[@name='name'] = 'teststop'",
             "/response/lst[@name='fieldType']/str[@name='class'] = 'solr.TextField'",
             "/response/lst[@name='fieldType']/lst[@name='analyzer']/lst[@name='tokenizer']/str[@name='class'] = 'solr.LowerCaseTokenizerFactory'",
             "/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst/str[@name='class'][.='solr.StandardFilterFactory']",
             "/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst/str[@name='class'][.='solr.StopFilterFactory']",
-            "/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst/str[@name='words'][.='stopwords.txt']",
-            "/response/lst[@name='fieldType']/arr[@name='fields']/str[.='teststop']",
-            "/response/lst[@name='fieldType']/arr[@name='dynamicFields']");
+            "/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst/str[@name='words'][.='stopwords.txt']"
+            );
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaDynamicFieldResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaDynamicFieldResource.java b/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaDynamicFieldResource.java
deleted file mode 100644
index 6572709..0000000
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaDynamicFieldResource.java
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * 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.
- */
-package org.apache.solr.rest.schema;
-import org.apache.commons.io.FileUtils;
-import org.apache.solr.util.RestTestBase;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.restlet.ext.servlet.ServerServlet;
-
-import java.io.File;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.regex.Pattern;
-
-public class TestManagedSchemaDynamicFieldResource extends RestTestBase {
-
-  private static File tmpSolrHome;
-  private static File tmpConfDir;
-
-  private static final String collection = "collection1";
-  private static final String confDir = collection + "/conf";
-
-
-  @Before
-  public void before() throws Exception {
-    tmpSolrHome = createTempDir().toFile();
-    tmpConfDir = new File(tmpSolrHome, confDir);
-    FileUtils.copyDirectory(new File(TEST_HOME()), tmpSolrHome.getAbsoluteFile());
-
-    final SortedMap<ServletHolder,String> extraServlets = new TreeMap<>();
-    final ServletHolder solrRestApi = new ServletHolder("SolrSchemaRestApi", ServerServlet.class);
-    solrRestApi.setInitParameter("org.restlet.application", "org.apache.solr.rest.SolrSchemaRestApi");
-    extraServlets.put(solrRestApi, "/schema/*");  // '/schema/*' matches '/schema', '/schema/', and '/schema/whatever...'
-
-    System.setProperty("managed.schema.mutable", "true");
-    System.setProperty("enable.update.log", "false");
-
-    createJettyAndHarness(tmpSolrHome.getAbsolutePath(), "solrconfig-managed-schema.xml", "schema-rest.xml",
-                          "/solr", true, extraServlets);
-  }
-
-  @After
-  public void after() throws Exception {
-    if (jetty != null) {
-      jetty.stop();
-      jetty = null;
-    }
-    client = null;
-    if (restTestHarness != null) {
-      restTestHarness.close();
-    }
-    restTestHarness = null;
-  }
-
-  @Test
-  public void testAddDynamicFieldBadFieldType() throws Exception {
-    assertJPut("/schema/dynamicfields/*_newdynamicfield",
-               json( "{'type':'not_in_there_at_all','stored':false}" ),
-               "/error/msg==\"Dynamic field \\'*_newdynamicfield\\': Field type \\'not_in_there_at_all\\' not found.\"");
-  }
-
-  @Test
-  public void testAddDynamicFieldMismatchedName() throws Exception {
-    assertJPut("/schema/dynamicfields/*_newdynamicfield",
-               json( "{'name':'*_something_else','type':'text','stored':false}" ),
-               "/error/msg=='///regex:\\\\*_newdynamicfield///'");
-  }
-
-  @Test
-  public void testAddDynamicFieldBadProperty() throws Exception {
-    assertJPut("/schema/dynamicfields/*_newdynamicfield",
-               json( "{'type':'text','no_property_with_this_name':false}" ),
-               "/error/msg==\"java.lang.IllegalArgumentException: Invalid field property: no_property_with_this_name\"");
-  }
-
-  @Test
-  public void testAddDynamicField() throws Exception {
-    assertQ("/schema/dynamicfields/newdynamicfield_*?indent=on&wt=xml",
-            "count(/response/lst[@name='newdynamicfield_*']) = 0",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '404'",
-            "/response/lst[@name='error']/int[@name='code'] = '404'");
-
-    assertJPut("/schema/dynamicfields/newdynamicfield_*",
-               json("{'type':'text','stored':false}"),
-               "/responseHeader/status==0");
-
-    assertQ("/schema/dynamicfields/newdynamicfield_*?indent=on&wt=xml",
-            "count(/response/lst[@name='dynamicField']) = 1",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'");
-
-    assertU(adoc("newdynamicfield_A", "value1 value2", "id", "123"));
-    assertU(commit());
-
-    assertQ("/select?q=newdynamicfield_A:value1",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
-            "/response/result[@name='response'][@numFound='1']",
-            "count(/response/result[@name='response']/doc/*) = 1",
-            "/response/result[@name='response']/doc/str[@name='id'][.='123']");
-  }
-
-  @Test
-  public void testAddDynamicFieldWithMulipleOptions() throws Exception {
-    assertQ("/schema/dynamicfields/newdynamicfield_*?indent=on&wt=xml",
-            "count(/response/lst[@name='dynamicField']) = 0",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '404'",
-            "/response/lst[@name='error']/int[@name='code'] = '404'");
-
-    assertJPut("/schema/dynamicfields/newdynamicfield_*",
-               json("{'type':'text_en','stored':true,'indexed':false}"),
-               "/responseHeader/status==0");
-
-    File managedSchemaFile = new File(tmpConfDir, "managed-schema");
-    assertTrue(managedSchemaFile.exists());
-    String managedSchemaContents = FileUtils.readFileToString(managedSchemaFile, "UTF-8");
-    Pattern newdynamicfieldStoredTrueIndexedFalsePattern
-        = Pattern.compile( "<dynamicField name=\"newdynamicfield_\\*\" type=\"text_en\""
-                         + "(?=.*stored=\"true\")(?=.*indexed=\"false\").*/>");
-    assertTrue(newdynamicfieldStoredTrueIndexedFalsePattern.matcher(managedSchemaContents).find());
-
-    assertQ("/schema/dynamicfields/newdynamicfield_*?indent=on&wt=xml",
-            "count(/response/lst[@name='dynamicField']) = 1",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
-            "/response/lst[@name='dynamicField']/str[@name='name'] = 'newdynamicfield_*'",
-            "/response/lst[@name='dynamicField']/str[@name='type'] = 'text_en'",
-            "/response/lst[@name='dynamicField']/bool[@name='indexed'] = 'false'",
-            "/response/lst[@name='dynamicField']/bool[@name='stored'] = 'true'");
-
-    assertU(adoc("newdynamicfield_A", "value1 value2", "id", "1234"));
-    assertU(commit());
-
-    assertQ("/schema/dynamicfields/newdynamicfield2_*?indent=on&wt=xml",
-            "count(/response/lst[@name='dynamicField']) = 0",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '404'",
-            "/response/lst[@name='error']/int[@name='code'] = '404'");
-
-    assertJPut("/schema/dynamicfields/newdynamicfield2_*",
-               json("{'type':'text_en','stored':true,'indexed':true,'multiValued':true}"),
-               "/responseHeader/status==0");
-
-    managedSchemaContents = FileUtils.readFileToString(managedSchemaFile, "UTF-8");
-    Pattern newdynamicfield2StoredTrueIndexedTrueMultiValuedTruePattern
-        = Pattern.compile( "<dynamicField name=\"newdynamicfield2_\\*\" type=\"text_en\" "
-                         + "(?=.*stored=\"true\")(?=.*indexed=\"true\")(?=.*multiValued=\"true\").*/>");
-    assertTrue(newdynamicfield2StoredTrueIndexedTrueMultiValuedTruePattern.matcher(managedSchemaContents).find());
-
-    assertQ("/schema/dynamicfields/newdynamicfield2_*?indent=on&wt=xml",
-            "count(/response/lst[@name='dynamicField']) = 1",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
-            "/response/lst[@name='dynamicField']/str[@name='name'] = 'newdynamicfield2_*'",
-            "/response/lst[@name='dynamicField']/str[@name='type'] = 'text_en'",
-            "/response/lst[@name='dynamicField']/bool[@name='indexed'] = 'true'",
-            "/response/lst[@name='dynamicField']/bool[@name='stored'] = 'true'",
-            "/response/lst[@name='dynamicField']/bool[@name='multiValued'] = 'true'");
-
-    assertU(adoc("newdynamicfield2_A", "value1 value2", "newdynamicfield2_A", "value3 value4", "id", "5678"));
-    assertU(commit());
-
-    assertQ("/select?q=newdynamicfield2_A:value3",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
-            "/response/result[@name='response'][@numFound='1']",
-            "count(/response/result[@name='response']/doc) = 1",
-            "/response/result[@name='response']/doc/str[@name='id'][.='5678']");
-  }
-
-  @Test
-  public void testAddDynamicFieldCollectionWithMultipleOptions() throws Exception {
-    assertQ("/schema/dynamicfields?indent=on&wt=xml",
-            "count(/response/arr[@name='dynamicFields']/lst/str[@name]) > 0",                          // there are fields
-            "count(/response/arr[@name='dynamicFields']/lst/str[starts-with(@name,'newfield')]) = 0"); // but none named newfield*
-
-    assertJPost("/schema/dynamicfields",
-                json("[{'name':'newdynamicfield_*','type':'text_en','stored':true,'indexed':false}]"),
-                "/responseHeader/status==0");
-
-    File managedSchemaFile = new File(tmpConfDir, "managed-schema");
-    assertTrue(managedSchemaFile.exists());
-    String managedSchemaContents = FileUtils.readFileToString(managedSchemaFile, "UTF-8");
-    Pattern newfieldStoredTrueIndexedFalsePattern
-        = Pattern.compile( "<dynamicField name=\"newdynamicfield_\\*\" type=\"text_en\""
-                         + "(?=.*stored=\"true\")(?=.*indexed=\"false\").*/>");
-    assertTrue(newfieldStoredTrueIndexedFalsePattern.matcher(managedSchemaContents).find());
-
-    assertQ("/schema/dynamicfields?indent=on&wt=xml",
-             "/response/arr[@name='dynamicFields']/lst"
-           + "[str[@name='name']='newdynamicfield_*' and str[@name='type']='text_en'"
-           + " and bool[@name='stored']='true' and bool[@name='indexed']='false']");
-
-    assertU(adoc("newdynamicfield_A", "value1 value2", "id", "789"));
-    assertU(commit());
-
-    assertJPost("/schema/dynamicfields",
-                json("[{'name':'newdynamicfield2_*','type':'text_en','stored':true,'indexed':true,'multiValued':true}]"),
-                "/responseHeader/status==0");
-
-    managedSchemaContents = FileUtils.readFileToString(managedSchemaFile, "UTF-8");
-    Pattern newdynamicfield2StoredTrueIndexedTrueMultiValuedTruePattern
-        = Pattern.compile( "<dynamicField name=\"newdynamicfield2_\\*\" type=\"text_en\" "
-                         + "(?=.*stored=\"true\")(?=.*indexed=\"true\")(?=.*multiValued=\"true\").*/>");
-    assertTrue(newdynamicfield2StoredTrueIndexedTrueMultiValuedTruePattern.matcher(managedSchemaContents).find());
-
-    assertQ("/schema/dynamicfields?indent=on&wt=xml",
-             "/response/arr[@name='dynamicFields']/lst"
-           + "[str[@name='name']='newdynamicfield2_*' and str[@name='type']='text_en'"
-           + " and bool[@name='stored']='true' and bool[@name='indexed']='true' and bool[@name='multiValued']='true']");
-
-    assertU(adoc("newdynamicfield2_A", "value1 value2", "newdynamicfield2_A", "value3 value4", "id", "790"));
-    assertU(commit());
-
-    assertQ("/select?q=newdynamicfield2_A:value3",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
-            "/response/result[@name='response'][@numFound='1']",
-            "count(/response/result[@name='response']/doc) = 1",
-            "/response/result[@name='response']/doc/str[@name='id'][.='790']");
-  }
-
-
-  @Test
-  public void testAddCopyField() throws Exception {
-    assertQ("/schema/dynamicfields/newdynamicfield2_*?indent=on&wt=xml",
-            "count(/response/lst[@name='dynamicField']) = 0",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '404'",
-            "/response/lst[@name='error']/int[@name='code'] = '404'");
-
-    assertJPut("/schema/dynamicfields/dynamicfieldA_*",
-               json("{'type':'text','stored':false}"),
-               "/responseHeader/status==0");
-    assertJPut("/schema/dynamicfields/dynamicfieldB_*",
-               json("{'type':'text','stored':false, 'copyFields':['dynamicfieldA_*']}"),
-               "/responseHeader/status==0");
-    assertJPut("/schema/dynamicfields/dynamicfieldC_*",
-               json("{'type':'text','stored':false, 'copyFields':'dynamicfieldA_*'}"),
-               "/responseHeader/status==0");
-
-    assertQ("/schema/dynamicfields/dynamicfieldB_*?indent=on&wt=xml",
-            "count(/response/lst[@name='dynamicField']) = 1",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'");
-    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=dynamicfieldB_*",
-            "count(/response/arr[@name='copyFields']/lst) = 1");
-    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=dynamicfieldC_*",
-            "count(/response/arr[@name='copyFields']/lst) = 1");
-    //fine to pass in empty list, just won't do anything
-    assertJPut("/schema/dynamicfields/dynamicfieldD_*",
-               json("{'type':'text','stored':false, 'copyFields':[]}"),
-               "/responseHeader/status==0");
-    //some bad usages
-    assertJPut("/schema/dynamicfields/dynamicfieldF_*",
-               json("{'type':'text','stored':false, 'copyFields':['some_nonexistent_dynamicfield_ignore_exception_*']}"),
-               "/error/msg==\"copyField dest :\\'some_nonexistent_dynamicfield_ignore_exception_*\\' is not an explicit field and doesn\\'t match a dynamicField.\"");
-  }
-
-  @Test
-  public void testPostMultipleDynamicFields() throws Exception {
-    assertQ("/schema/dynamicfields/newdynamicfield1_*?indent=on&wt=xml",
-            "count(/response/lst[@name='dynamicField']) = 0",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '404'",
-            "/response/lst[@name='error']/int[@name='code'] = '404'");
-
-    assertQ("/schema/dynamicfields/newdynamicfield2_*?indent=on&wt=xml",
-            "count(/response/lst[@name='dynamicField']) = 0",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '404'",
-            "/response/lst[@name='error']/int[@name='code'] = '404'");
-
-    assertJPost("/schema/dynamicfields",
-                json( "[{'name':'newdynamicfield1_*','type':'text','stored':false},"
-                    + " {'name':'newdynamicfield2_*','type':'text','stored':false}]"),
-                "/responseHeader/status==0");
-
-    assertQ("/schema/dynamicfields/newdynamicfield1_*?indent=on&wt=xml",
-            "count(/response/lst[@name='dynamicField']) = 1",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'");
-
-    assertQ("/schema/dynamicfields/newdynamicfield2_*?indent=on&wt=xml",
-            "count(/response/lst[@name='dynamicField']) = 1",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'");
-
-    assertU(adoc("newdynamicfield1_A", "value1 value2", "id", "123"));
-    assertU(adoc("newdynamicfield2_A", "value3 value4", "id", "456"));
-    assertU(commit());
-
-    assertQ("/select?q=newdynamicfield1_A:value1",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
-            "/response/result[@name='response'][@numFound='1']",
-            "count(/response/result[@name='response']/doc/*) = 1",
-            "/response/result[@name='response']/doc/str[@name='id'][.='123']");
-    assertQ("/select?q=newdynamicfield2_A:value3",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
-            "/response/result[@name='response'][@numFound='1']",
-            "count(/response/result[@name='response']/doc/*) = 1",
-            "/response/result[@name='response']/doc/str[@name='id'][.='456']");
-  }
-
-  @Test
-  public void testPostCopy() throws Exception {
-    assertJPost("/schema/dynamicfields",
-                json( "[{'name':'dynamicfieldA_*','type':'text','stored':false},"
-                    + " {'name':'dynamicfieldB_*','type':'text','stored':false},"
-                    + " {'name':'dynamicfieldC_*','type':'text','stored':false, 'copyFields':['dynamicfieldB_*']}]"),
-                "/responseHeader/status==0");
-    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=dynamicfieldC_*",
-            "count(/response/arr[@name='copyFields']/lst) = 1");
-    assertJPost("/schema/dynamicfields",
-                json( "[{'name':'dynamicfieldD_*','type':'text','stored':false},"
-                    + " {'name':'dynamicfieldE_*','type':'text','stored':false},"
-                    + " {'name':'dynamicfieldF_*','type':'text','stored':false, 'copyFields':['dynamicfieldD_*','dynamicfieldE_*']},"
-                    + " {'name':'dynamicfieldG_*','type':'text','stored':false, 'copyFields':'dynamicfieldD_*'}]"),//single
-                "/responseHeader/status==0");
-    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=dynamicfieldF_*",
-            "count(/response/arr[@name='copyFields']/lst) = 2");
-    //passing in an empty list is perfectly acceptable, it just won't do anything
-    assertJPost("/schema/dynamicfields",
-                json( "[{'name':'dynamicfieldX_*','type':'text','stored':false},"
-                    + " {'name':'dynamicfieldY_*','type':'text','stored':false},"
-                    + " {'name':'dynamicfieldZ_*','type':'text','stored':false, 'copyFields':[]}]"),
-                "/responseHeader/status==0");
-    //some bad usages
-
-    assertJPost("/schema/dynamicfields",
-                json( "[{'name':'dynamicfieldH_*','type':'text','stored':false},"
-                    + " {'name':'dynamicfieldI_*','type':'text','stored':false},"
-                    + " {'name':'dynamicfieldJ_*','type':'text','stored':false, 'copyFields':['some_nonexistent_dynamicfield_ignore_exception_*']}]"),
-                "/error/msg=='copyField dest :\\'some_nonexistent_dynamicfield_ignore_exception_*\\' is not an explicit field and doesn\\'t match a dynamicField.'");
-  }
-
-  @Test
-  public void testPostCopyFields() throws Exception {
-    assertJPost("/schema/dynamicfields",
-                json( "[{'name':'dynamicfieldA_*','type':'text','stored':false},"
-                    + " {'name':'dynamicfieldB_*','type':'text','stored':false},"
-                    + " {'name':'dynamicfieldC_*','type':'text','stored':false},"
-                    + " {'name':'dynamicfieldD_*','type':'text','stored':false},"
-                    + " {'name':'dynamicfieldE_*','type':'text','stored':false}]"),
-                "/responseHeader/status==0");
-    assertJPost("/schema/copyfields",
-                json( "[{'source':'dynamicfieldA_*', 'dest':'dynamicfieldB_*'},"
-                    + " {'source':'dynamicfieldD_*', 'dest':['dynamicfieldC_*', 'dynamicfieldE_*']}]"),
-                "/responseHeader/status==0");
-    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=dynamicfieldA_*",
-            "count(/response/arr[@name='copyFields']/lst) = 1");
-    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=dynamicfieldD_*",
-            "count(/response/arr[@name='copyFields']/lst) = 2");
-    assertJPost("/schema/copyfields", // copyField glob sources are not required to match a dynamic field
-                json("[{'source':'some_glob_not_necessarily_matching_any_dynamicfield_*', 'dest':['dynamicfieldA_*']},"
-                    +" {'source':'*', 'dest':['dynamicfieldD_*']}]"),
-                "/responseHeader/status==0");
-    assertJPost("/schema/copyfields",
-                json("[{'source':'dynamicfieldD_*', 'dest':['some_nonexistent_dynamicfield_ignore_exception_*']}]"),
-                "/error/msg=='copyField dest :\\'some_nonexistent_dynamicfield_ignore_exception_*\\' is not an explicit field and doesn\\'t match a dynamicField.'");
-  }
-}
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldResource.java b/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldResource.java
deleted file mode 100644
index b39d266..0000000
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldResource.java
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * 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.
- */
-package org.apache.solr.rest.schema;
-import org.apache.commons.io.FileUtils;
-import org.apache.solr.util.RestTestBase;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.restlet.ext.servlet.ServerServlet;
-
-import java.io.File;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.regex.Pattern;
-
-public class TestManagedSchemaFieldResource extends RestTestBase {
-
-  private static File tmpSolrHome;
-  private static File tmpConfDir;
-
-  private static final String collection = "collection1";
-  private static final String confDir = collection + "/conf";
-
-
-  @Before
-  public void before() throws Exception {
-    tmpSolrHome = createTempDir().toFile();
-    tmpConfDir = new File(tmpSolrHome, confDir);
-    FileUtils.copyDirectory(new File(TEST_HOME()), tmpSolrHome.getAbsoluteFile());
-
-    final SortedMap<ServletHolder,String> extraServlets = new TreeMap<>();
-    final ServletHolder solrRestApi = new ServletHolder("SolrSchemaRestApi", ServerServlet.class);
-    solrRestApi.setInitParameter("org.restlet.application", "org.apache.solr.rest.SolrSchemaRestApi");
-    extraServlets.put(solrRestApi, "/schema/*");  // '/schema/*' matches '/schema', '/schema/', and '/schema/whatever...'
-
-    System.setProperty("managed.schema.mutable", "true");
-    System.setProperty("enable.update.log", "false");
-
-    createJettyAndHarness(tmpSolrHome.getAbsolutePath(), "solrconfig-managed-schema.xml", "schema-rest.xml",
-                          "/solr", true, extraServlets);
-  }
-
-  @After
-  public void after() throws Exception {
-    if (jetty != null) {
-      jetty.stop();
-      jetty = null;
-    }
-    client = null;
-    if (restTestHarness != null) {
-      restTestHarness.close();
-    }
-    restTestHarness = null;
-  }
-  
-  @Test
-  public void testAddFieldBadFieldType() throws Exception {
-    assertJPut("/schema/fields/newfield",
-        json( "{'type':'not_in_there_at_all','stored':false}" ),
-        "/error/msg==\"Field \\'newfield\\': Field type \\'not_in_there_at_all\\' not found.\"");
-  }
-
-  @Test
-  public void testAddFieldMismatchedName() throws Exception {
-    assertJPut("/schema/fields/newfield",
-        json( "{'name':'something_else','type':'text','stored':false}" ),
-        "/error/msg=='///regex:newfield///'");
-  }
-  
-  @Test
-  public void testAddFieldBadProperty() throws Exception {
-    assertJPut("/schema/fields/newfield",
-               json( "{'type':'text','no_property_with_this_name':false}" ),
-               "/error/msg==\"java.lang.IllegalArgumentException: Invalid field property: no_property_with_this_name\"");
-  }
-  
-  @Test
-  public void testAddField() throws Exception {
-    assertQ("/schema/fields/newfield?indent=on&wt=xml",
-            "count(/response/lst[@name='field']) = 0",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '404'",
-            "/response/lst[@name='error']/int[@name='code'] = '404'");
-    
-    assertJPut("/schema/fields/newfield",
-               json("{'type':'text','stored':false}"),
-               "/responseHeader/status==0");
-    
-    assertQ("/schema/fields/newfield?indent=on&wt=xml",
-            "count(/response/lst[@name='field']) = 1",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'");
-    
-    assertU(adoc("newfield", "value1 value2", "id", "123"));
-    assertU(commit());
-
-    assertQ("/select?q=newfield:value1",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
-            "/response/result[@name='response'][@numFound='1']",
-            "count(/response/result[@name='response']/doc/*) = 1",
-            "/response/result[@name='response']/doc/str[@name='id'][.='123']");
-  }
-
-  @Test
-  public void testAddFieldWithMulipleOptions() throws Exception {
-    assertQ("/schema/fields/newfield?indent=on&wt=xml",
-            "count(/response/lst[@name='field']) = 0",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '404'",
-            "/response/lst[@name='error']/int[@name='code'] = '404'");
-
-    assertJPut("/schema/fields/newfield",
-               json("{'type':'text_en','stored':true,'indexed':false}"),
-               "/responseHeader/status==0");
-
-    File managedSchemaFile = new File(tmpConfDir, "managed-schema");
-    assertTrue(managedSchemaFile.exists());
-    String managedSchemaContents = FileUtils.readFileToString(managedSchemaFile, "UTF-8");
-    Pattern newfieldStoredTrueIndexedFalsePattern 
-        = Pattern.compile( "<field name=\"newfield\" type=\"text_en\" "
-                         + "(?=.*stored=\"true\")(?=.*indexed=\"false\").*/>");
-    assertTrue(newfieldStoredTrueIndexedFalsePattern.matcher(managedSchemaContents).find());
-
-    assertQ("/schema/fields/newfield?indent=on&wt=xml",
-            "count(/response/lst[@name='field']) = 1",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
-            "/response/lst[@name='field']/str[@name='name'] = 'newfield'",
-            "/response/lst[@name='field']/str[@name='type'] = 'text_en'",
-            "/response/lst[@name='field']/bool[@name='indexed'] = 'false'",
-            "/response/lst[@name='field']/bool[@name='stored'] = 'true'");
-
-    assertU(adoc("newfield", "value1 value2", "id", "1234"));
-    assertU(commit());
-
-    assertQ("/schema/fields/newfield2?indent=on&wt=xml",
-            "count(/response/lst[@name='field']) = 0",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '404'",
-            "/response/lst[@name='error']/int[@name='code'] = '404'");
-
-    assertJPut("/schema/fields/newfield2",
-               json("{'type':'text_en','stored':true,'indexed':true,'multiValued':true}"),
-               "/responseHeader/status==0");
-
-    managedSchemaContents = FileUtils.readFileToString(managedSchemaFile, "UTF-8");
-    Pattern newfield2StoredTrueIndexedTrueMultiValuedTruePattern
-        = Pattern.compile( "<field name=\"newfield2\" type=\"text_en\" "
-                         + "(?=.*stored=\"true\")(?=.*indexed=\"true\")(?=.*multiValued=\"true\").*/>");
-    assertTrue(newfield2StoredTrueIndexedTrueMultiValuedTruePattern.matcher(managedSchemaContents).find());
-
-    assertQ("/schema/fields/newfield2?indent=on&wt=xml",
-            "count(/response/lst[@name='field']) = 1",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
-            "/response/lst[@name='field']/str[@name='name'] = 'newfield2'",
-            "/response/lst[@name='field']/str[@name='type'] = 'text_en'",
-            "/response/lst[@name='field']/bool[@name='indexed'] = 'true'",
-            "/response/lst[@name='field']/bool[@name='stored'] = 'true'",
-            "/response/lst[@name='field']/bool[@name='multiValued'] = 'true'");
-
-    assertU(adoc("newfield2", "value1 value2", "newfield2", "value3 value4", "id", "5678"));
-    assertU(commit());
-
-    assertQ("/select?q=newfield2:value3",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
-            "/response/result[@name='response'][@numFound='1']",
-            "count(/response/result[@name='response']/doc) = 1",
-            "/response/result[@name='response']/doc/str[@name='id'][.='5678']");
-  }
-
-  @Test
-  public void testAddFieldCollectionWithMultipleOptions() throws Exception {
-    assertQ("/schema/fields?indent=on&wt=xml",
-            "count(/response/arr[@name='fields']/lst/str[@name]) > 0",                          // there are fields
-            "count(/response/arr[@name='fields']/lst/str[starts-with(@name,'newfield')]) = 0"); // but none named newfield*
-
-    assertJPost("/schema/fields",
-               json("[{'name':'newfield','type':'text_en','stored':true,'indexed':false}]"),
-               "/responseHeader/status==0");
-
-    File managedSchemaFile = new File(tmpConfDir, "managed-schema");
-    assertTrue(managedSchemaFile.exists());
-    String managedSchemaContents = FileUtils.readFileToString(managedSchemaFile, "UTF-8");
-    Pattern newfieldStoredTrueIndexedFalsePattern
-        = Pattern.compile( "<field name=\"newfield\" type=\"text_en\" "
-                         + "(?=.*stored=\"true\")(?=.*indexed=\"false\").*/>");
-    assertTrue(newfieldStoredTrueIndexedFalsePattern.matcher(managedSchemaContents).find());
-
-    assertQ("/schema/fields?indent=on&wt=xml",
-             "/response/arr[@name='fields']/lst"
-           + "[str[@name='name']='newfield' and str[@name='type']='text_en'"
-           + " and bool[@name='stored']='true' and bool[@name='indexed']='false']");
-
-    assertU(adoc("newfield", "value1 value2", "id", "789"));
-    assertU(commit());
-
-    assertJPost("/schema/fields",
-                json("[{'name':'newfield2','type':'text_en','stored':true,'indexed':true,'multiValued':true}]"),
-                "/responseHeader/status==0");
-
-    managedSchemaContents = FileUtils.readFileToString(managedSchemaFile, "UTF-8");
-    Pattern newfield2StoredTrueIndexedTrueMultiValuedTruePattern
-        = Pattern.compile( "<field name=\"newfield2\" type=\"text_en\" "
-                         + "(?=.*stored=\"true\")(?=.*indexed=\"true\")(?=.*multiValued=\"true\").*/>");
-    assertTrue(newfield2StoredTrueIndexedTrueMultiValuedTruePattern.matcher(managedSchemaContents).find());
-
-    assertQ("/schema/fields?indent=on&wt=xml",
-            "/response/arr[@name='fields']/lst"
-            + "[str[@name='name']='newfield2' and str[@name='type']='text_en'"
-            + " and bool[@name='stored']='true' and bool[@name='indexed']='true' and bool[@name='multiValued']='true']");
-
-    assertU(adoc("newfield2", "value1 value2", "newfield2", "value3 value4", "id", "790"));
-    assertU(commit());
-
-    assertQ("/select?q=newfield2:value3",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
-            "/response/result[@name='response'][@numFound='1']",
-            "count(/response/result[@name='response']/doc) = 1",
-            "/response/result[@name='response']/doc/str[@name='id'][.='790']");
-  }
-
-
-  @Test
-  public void testAddCopyField() throws Exception {
-    assertQ("/schema/fields/newfield2?indent=on&wt=xml",
-            "count(/response/lst[@name='field']) = 0",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '404'",
-            "/response/lst[@name='error']/int[@name='code'] = '404'");
-
-    assertJPut("/schema/fields/fieldA", 
-               json("{'type':'text','stored':false}"),
-               "/responseHeader/status==0");
-    assertJPut("/schema/fields/fieldB",
-               json("{'type':'text','stored':false, 'copyFields':['fieldA']}"),
-               "/responseHeader/status==0");
-    assertJPut("/schema/fields/fieldC",
-               json("{'type':'text','stored':false, 'copyFields':'fieldA'}"),
-               "/responseHeader/status==0");
-
-    assertQ("/schema/fields/fieldB?indent=on&wt=xml",
-            "count(/response/lst[@name='field']) = 1",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'");
-    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=fieldB",
-        "count(/response/arr[@name='copyFields']/lst) = 1"
-    );
-    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=fieldC",
-        "count(/response/arr[@name='copyFields']/lst) = 1"
-    );
-    //fine to pass in empty list, just won't do anything
-    assertJPut("/schema/fields/fieldD",
-               json("{'type':'text','stored':false, 'copyFields':[]}"),
-               "/responseHeader/status==0");
-    //some bad usages
-    assertJPut("/schema/fields/fieldF",
-               json("{'type':'text','stored':false, 'copyFields':['some_nonexistent_field_ignore_exception']}"),
-               "/error/msg==\"copyField dest :\\'some_nonexistent_field_ignore_exception\\' is not an explicit field and doesn\\'t match a dynamicField.\"");
-  }
-
-  @Test
-  public void testPostMultipleFields() throws Exception {
-    assertQ("/schema/fields/newfield1?indent=on&wt=xml",
-            "count(/response/lst[@name='field']) = 0",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '404'",
-            "/response/lst[@name='error']/int[@name='code'] = '404'");
-
-    assertQ("/schema/fields/newfield2?indent=on&wt=xml",
-            "count(/response/lst[@name='field']) = 0",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '404'",
-            "/response/lst[@name='error']/int[@name='code'] = '404'");
-
-    assertJPost("/schema/fields",
-                json( "[{'name':'newfield1','type':'text','stored':false},"
-                    + " {'name':'newfield2','type':'text','stored':false}]"),
-                "/responseHeader/status==0");
-
-    assertQ("/schema/fields/newfield1?indent=on&wt=xml",
-            "count(/response/lst[@name='field']) = 1",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'");
-
-    assertQ("/schema/fields/newfield2?indent=on&wt=xml",
-            "count(/response/lst[@name='field']) = 1",
-            "/response/lst[@name='responseHeader']/int[@name='status'] = '0'");
-
-    assertU(adoc("newfield1", "value1 value2", "id", "123"));
-    assertU(adoc("newfield2", "value3 value4", "id", "456"));
-    assertU(commit());
-
-    assertQ("/select?q=newfield1:value1",
-        "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
-        "/response/result[@name='response'][@numFound='1']",
-        "count(/response/result[@name='response']/doc/*) = 1",
-        "/response/result[@name='response']/doc/str[@name='id'][.='123']");
-    assertQ("/select?q=newfield2:value3",
-        "/response/lst[@name='responseHeader']/int[@name='status'] = '0'",
-        "/response/result[@name='response'][@numFound='1']",
-        "count(/response/result[@name='response']/doc/*) = 1",
-        "/response/result[@name='response']/doc/str[@name='id'][.='456']");
-  }
-
-  @Test
-  public void testPostCopy() throws Exception {
-    assertJPost("/schema/fields",
-                json( "[{'name':'fieldA','type':'text','stored':false},"
-                    + " {'name':'fieldB','type':'text','stored':false},"
-                    + " {'name':'fieldC','type':'text','stored':false, 'copyFields':['fieldB']}]"),
-                "/responseHeader/status==0");
-    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=fieldC",
-        "count(/response/arr[@name='copyFields']/lst) = 1"
-    );
-    assertJPost("/schema/fields",
-                json( "[{'name':'fieldD','type':'text','stored':false},"
-                    + " {'name':'fieldE','type':'text','stored':false},"
-                    + " {'name':'fieldF','type':'text','stored':false, 'copyFields':['fieldD','fieldE']},"
-                    + " {'name':'fieldG','type':'text','stored':false, 'copyFields':'fieldD'}]"),//single
-                "/responseHeader/status==0");
-    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=fieldF",
-        "count(/response/arr[@name='copyFields']/lst) = 2"
-    );
-    //passing in an empty list is perfectly acceptable, it just won't do anything
-    assertJPost("/schema/fields",
-                json( "[{'name':'fieldX','type':'text','stored':false},"
-                    + " {'name':'fieldY','type':'text','stored':false},"
-                    + " {'name':'fieldZ','type':'text','stored':false, 'copyFields':[]}]"),
-                "/responseHeader/status==0");
-    //some bad usages
-
-    assertJPost("/schema/fields",
-                json( "[{'name':'fieldH','type':'text','stored':false},"
-                    + " {'name':'fieldI','type':'text','stored':false},"
-                    + " {'name':'fieldJ','type':'text','stored':false, 'copyFields':['some_nonexistent_field_ignore_exception']}]"),
-                "/error/msg=='copyField dest :\\'some_nonexistent_field_ignore_exception\\' is not an explicit field and doesn\\'t match a dynamicField.'");
-  }
-
-  @Test
-  public void testPostCopyFields() throws Exception {
-    assertJPost("/schema/fields",
-                json( "[{'name':'fieldA','type':'text','stored':false},"
-                    + " {'name':'fieldB','type':'text','stored':false},"
-                    + " {'name':'fieldC','type':'text','stored':false},"
-                    + " {'name':'fieldD','type':'text','stored':false},"
-                    + " {'name':'fieldE','type':'text','stored':false}]"),
-                "/responseHeader/status==0");
-    assertJPost("/schema/copyfields", 
-                json( "[{'source':'fieldA', 'dest':'fieldB'},"
-                    + " {'source':'fieldD', 'dest':['fieldC', 'fieldE']}]"),
-                "/responseHeader/status==0");
-    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=fieldA",
-        "count(/response/arr[@name='copyFields']/lst) = 1");
-    assertQ("/schema/copyfields/?indent=on&wt=xml&source.fl=fieldD",
-        "count(/response/arr[@name='copyFields']/lst) = 2");
-    assertJPost("/schema/copyfields", 
-                json("[{'source':'some_nonexistent_field_ignore_exception', 'dest':['fieldA']}]"),
-                "/error/msg=='copyField source :\\'some_nonexistent_field_ignore_exception\\' is not a glob and doesn\\'t match any explicit field or dynamicField.'");
-    assertJPost("/schema/copyfields", 
-                json("[{'source':'fieldD', 'dest':['some_nonexistent_field_ignore_exception']}]"),
-                "/error/msg=='copyField dest :\\'some_nonexistent_field_ignore_exception\\' is not an explicit field and doesn\\'t match a dynamicField.'");
-  }
-}
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f2c281ab/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldTypeResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldTypeResource.java b/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldTypeResource.java
deleted file mode 100644
index a0f4e25..0000000
--- a/solr/core/src/test/org/apache/solr/rest/schema/TestManagedSchemaFieldTypeResource.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * 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.
- */
-package org.apache.solr.rest.schema;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.solr.util.RestTestBase;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.noggit.JSONUtil;
-import org.restlet.ext.servlet.ServerServlet;
-
-public class TestManagedSchemaFieldTypeResource extends RestTestBase {
-  
-  private static File tmpSolrHome;
-  private static File tmpConfDir;
-
-  private static final String collection = "collection1";
-  private static final String confDir = collection + "/conf";
-
-  @Before
-  public void before() throws Exception {
-    tmpSolrHome = createTempDir().toFile();
-    tmpConfDir = new File(tmpSolrHome, confDir);
-    FileUtils.copyDirectory(new File(TEST_HOME()), tmpSolrHome.getAbsoluteFile());
-
-    final SortedMap<ServletHolder,String> extraServlets = new TreeMap<>();
-    final ServletHolder solrRestApi = new ServletHolder("SolrSchemaRestApi", ServerServlet.class);
-    solrRestApi.setInitParameter("org.restlet.application", "org.apache.solr.rest.SolrSchemaRestApi");
-    extraServlets.put(solrRestApi, "/schema/*");  // '/schema/*' matches '/schema', '/schema/', and '/schema/whatever...'
-
-    System.setProperty("managed.schema.mutable", "true");
-    System.setProperty("enable.update.log", "false");
-
-    createJettyAndHarness(tmpSolrHome.getAbsolutePath(), "solrconfig-managed-schema.xml", "schema-rest.xml",
-                          "/solr", true, extraServlets);
-  }
-
-  @After
-  private void after() throws Exception {
-    jetty.stop();
-    jetty = null;
-    System.clearProperty("managed.schema.mutable");
-    System.clearProperty("enable.update.log");
-    
-    if (restTestHarness != null) {
-      restTestHarness.close();
-    }
-    restTestHarness = null;
-  }
-  
-  @Test
-  public void testAddFieldTypes() throws Exception {
-    
-    // name mismatch
-    assertJPut("/schema/fieldtypes/myIntFieldType",
-        json("{'name':'badNameEh','class':'solr.TrieIntField','stored':false}"),
-        "/responseHeader/status==400");    
-    
-    // no class
-    assertJPut("/schema/fieldtypes/myIntFieldType",
-        json("{'stored':false}"),
-        "/responseHeader/status==400");
-    
-    // invalid attribute
-    assertJPut("/schema/fieldtypes/myIntFieldType",
-        json("{'foo':'bar'}"),
-        "/responseHeader/status==400");
-    
-    // empty analyzer
-    String ftdef = "";
-    ftdef += "{";
-    ftdef += "  'class':'solr.TextField','positionIncrementGap':'100',";
-    ftdef += "  'analyzer':''";
-    ftdef += "}";    
-    assertJPut("/schema/fieldtypes/emptyAnalyzerFieldType",
-        json(ftdef),
-        "/responseHeader/status==400");
-
-    // basic field types
-    assertJPut("/schema/fieldtypes/myIntFieldType",
-        json("{'name':'myIntFieldType','class':'solr.TrieIntField','stored':false}"),
-        "/responseHeader/status==0");    
-    checkFieldTypeProps(getExpectedProps("myIntFieldType", "solr.TrieIntField", true, false), 16);
-    
-    assertJPut("/schema/fieldtypes/myDoubleFieldType",
-        json("{'class':'solr.TrieDoubleField','precisionStep':'0','positionIncrementGap':'0'}"),
-        "/responseHeader/status==0");
-    Map<String,Object> expProps = 
-        getExpectedProps("myDoubleFieldType", "solr.TrieDoubleField", true, true);
-    // add some additional expected props for this type
-    expProps.put("precisionStep", "0");
-    expProps.put("positionIncrementGap", "0");
-    checkFieldTypeProps(expProps, 18);
-    
-    assertJPut("/schema/fieldtypes/myBoolFieldType",
-        json("{'class':'solr.BoolField','sortMissingLast':true}"),
-        "/responseHeader/status==0");
-    expProps = getExpectedProps("myBoolFieldType", "solr.BoolField", true, true);
-    expProps.put("sortMissingLast", true);
-    checkFieldTypeProps(expProps, 17);    
-    
-    // a text analyzing field type
-    ftdef = "{";
-    ftdef += "  'class':'solr.TextField','positionIncrementGap':'100',";
-    ftdef += "  'analyzer':{";
-    ftdef += "    'charFilters':[";
-    ftdef += "       {'class':'solr.PatternReplaceCharFilterFactory','replacement':'$1$1','pattern':'([a-zA-Z])\\\\1+'}";
-    ftdef += "    ],";
-    ftdef += "    'tokenizer':{'class':'solr.WhitespaceTokenizerFactory'},";
-    ftdef += "    'filters':[";
-    ftdef += "       {'class':'solr.WordDelimiterFilterFactory','preserveOriginal':'0'},";
-    ftdef += "       {'class':'solr.StopFilterFactory','words':'stopwords.txt','ignoreCase':'true'},";
-    ftdef += "       {'class':'solr.LowerCaseFilterFactory'},";
-    ftdef += "       {'class':'solr.ASCIIFoldingFilterFactory'},";
-    ftdef += "       {'class':'solr.KStemFilterFactory'}";
-    ftdef += "    ]";
-    ftdef += "  }";
-    ftdef += "}";
-  
-    assertJPut("/schema/fieldtypes/myTextFieldType", json(ftdef), "/responseHeader/status==0");
-    
-    expProps = getExpectedProps("myTextFieldType", "solr.TextField", true, true);
-    expProps.put("autoGeneratePhraseQueries", false);
-    expProps.put("omitNorms", false);
-    expProps.put("omitTermFreqAndPositions", false);
-    expProps.put("omitPositions", false);
-    expProps.put("storeOffsetsWithPositions", false);
-    expProps.put("tokenized", true);
-            
-    List<String> analyzerTests = new ArrayList<>();
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='charFilters']/lst[1]/str[@name='class'] = 'solr.PatternReplaceCharFilterFactory'");
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/lst[@name='tokenizer']/str[@name='class'] = 'solr.WhitespaceTokenizerFactory'");
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst[1]/str[@name='class'] = 'solr.WordDelimiterFilterFactory'");
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst[2]/str[@name='class'] = 'solr.StopFilterFactory'");
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst[3]/str[@name='class'] = 'solr.LowerCaseFilterFactory'");
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst[4]/str[@name='class'] = 'solr.ASCIIFoldingFilterFactory'");
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst[5]/str[@name='class'] = 'solr.KStemFilterFactory'");
-    checkFieldTypeProps(expProps, 19, analyzerTests);    
-    
-    // now add a field type that uses managed resources and a field that uses that type
-    
-    String piglatinStopWordEndpoint = "/schema/analysis/stopwords/piglatin";            
-    String piglatinSynonymEndpoint = "/schema/analysis/synonyms/piglatin";    
-    
-    // now define a new FieldType that uses the managed piglatin endpoints
-    // the managed endpoints will be autovivified as needed 
-    ftdef = "{";
-    ftdef += "  'class':'solr.TextField',";
-    ftdef += "  'analyzer':{";
-    ftdef += "    'tokenizer':{'class':'solr.StandardTokenizerFactory'},";
-    ftdef += "    'filters':[";
-    ftdef += "       {'class':'solr.ManagedStopFilterFactory','managed':'piglatin'},";
-    ftdef += "       {'class':'solr.ManagedSynonymFilterFactory','managed':'piglatin'}";
-    ftdef += "    ]";
-    ftdef += "  }";
-    ftdef += "}";
-    assertJPut("/schema/fieldtypes/piglatinFieldType", json(ftdef), "/responseHeader/status==0");
-    
-    expProps = getExpectedProps("piglatinFieldType", "solr.TextField", true, true);
-    expProps.put("autoGeneratePhraseQueries", false);
-    expProps.put("omitNorms", false);
-    expProps.put("omitTermFreqAndPositions", false);
-    expProps.put("omitPositions", false);
-    expProps.put("storeOffsetsWithPositions", false);
-    expProps.put("tokenized", true);
-            
-    analyzerTests = new ArrayList<>();
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/lst[@name='tokenizer']/str[@name='class'] = 'solr.StandardTokenizerFactory'");
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst[1]/str[@name='class'] = 'solr.ManagedStopFilterFactory'");
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst[2]/str[@name='class'] = 'solr.ManagedSynonymFilterFactory'");
-    checkFieldTypeProps(expProps, 18, analyzerTests);
-    
-    assertJQ(piglatinSynonymEndpoint, 
-        "/synonymMappings/initArgs/ignoreCase==false",
-        "/synonymMappings/managedMap=={}");
-
-    // add some piglatin synonyms
-    Map<String,List<String>> syns = new HashMap<>();
-    syns.put("appyhay", Arrays.asList("ladgay","oyfuljay"));    
-    assertJPut(piglatinSynonymEndpoint, 
-              JSONUtil.toJSON(syns),
-              "/responseHeader/status==0");    
-    assertJQ(piglatinSynonymEndpoint, 
-            "/synonymMappings/managedMap/appyhay==['ladgay','oyfuljay']");
-    
-    // add some piglatin stopwords
-    assertJPut(piglatinStopWordEndpoint, 
-        JSONUtil.toJSON(Arrays.asList("hetay")),
-        "/responseHeader/status==0");
-   
-    assertJQ(piglatinStopWordEndpoint + "/hetay", "/hetay=='hetay'");
-    
-    // add a field that uses our new type
-    assertJPut("/schema/fields/newManagedField",
-        json("{'type':'piglatinFieldType','stored':false}"),
-        "/responseHeader/status==0");   
-    
-    assertQ("/schema/fields/newManagedField?indent=on&wt=xml",
-        "count(/response/lst[@name='field']) = 1",
-        "/response/lst[@name='responseHeader']/int[@name='status'] = '0'");
-
-    // try to delete the managed synonyms endpoint, which should fail because it is being used
-    assertJDelete(piglatinSynonymEndpoint, "/responseHeader/status==403");
-    
-    // test adding multiple field types at once
-    ftdef = "[";
-    ftdef += "{";
-    ftdef += "  'name':'textFieldType1',";
-    ftdef += "  'class':'solr.TextField','positionIncrementGap':'100',";
-    ftdef += "  'analyzer':{";
-    ftdef += "    'tokenizer':{'class':'solr.WhitespaceTokenizerFactory'},";
-    ftdef += "    'filters':[";
-    ftdef += "       {'class':'solr.WordDelimiterFilterFactory','preserveOriginal':'0'},";
-    ftdef += "       {'class':'solr.StopFilterFactory','words':'stopwords.txt','ignoreCase':'true'},";
-    ftdef += "       {'class':'solr.LowerCaseFilterFactory'}";
-    ftdef += "    ]";
-    ftdef += "  }";
-    ftdef += "},{";
-    ftdef += "  'name':'textFieldType2',";
-    ftdef += "  'class':'solr.TextField','positionIncrementGap':'100',";
-    ftdef += "  'analyzer':{";
-    ftdef += "    'tokenizer':{'class':'solr.WhitespaceTokenizerFactory'},";
-    ftdef += "    'filters':[";
-    ftdef += "       {'class':'solr.WordDelimiterFilterFactory','preserveOriginal':'0'},";
-    ftdef += "       {'class':'solr.StopFilterFactory','words':'stopwords.txt','ignoreCase':'true'},";
-    ftdef += "       {'class':'solr.LowerCaseFilterFactory'},";
-    ftdef += "       {'class':'solr.ASCIIFoldingFilterFactory'}";
-    ftdef += "    ]";
-    ftdef += "  }";
-    ftdef += "}";
-    ftdef += "]";
-  
-    assertJPost("/schema/fieldtypes", json(ftdef), "/responseHeader/status==0");
-    
-    expProps = getExpectedProps("textFieldType1", "solr.TextField", true, true);
-    expProps.put("autoGeneratePhraseQueries", false);
-    expProps.put("omitNorms", false);
-    expProps.put("omitTermFreqAndPositions", false);
-    expProps.put("omitPositions", false);
-    expProps.put("storeOffsetsWithPositions", false);
-    expProps.put("tokenized", true);
-            
-    analyzerTests = new ArrayList<>();
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/lst[@name='tokenizer']/str[@name='class'] = 'solr.WhitespaceTokenizerFactory'");
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst[1]/str[@name='class'] = 'solr.WordDelimiterFilterFactory'");
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst[2]/str[@name='class'] = 'solr.StopFilterFactory'");
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst[3]/str[@name='class'] = 'solr.LowerCaseFilterFactory'");
-    checkFieldTypeProps(expProps, 19, analyzerTests);    
-
-    expProps = getExpectedProps("textFieldType2", "solr.TextField", true, true);
-    expProps.put("autoGeneratePhraseQueries", false);
-    expProps.put("omitNorms", false);
-    expProps.put("omitTermFreqAndPositions", false);
-    expProps.put("omitPositions", false);
-    expProps.put("storeOffsetsWithPositions", false);
-    expProps.put("tokenized", true);
-            
-    analyzerTests = new ArrayList<>();
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/lst[@name='tokenizer']/str[@name='class'] = 'solr.WhitespaceTokenizerFactory'");
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst[1]/str[@name='class'] = 'solr.WordDelimiterFilterFactory'");
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst[2]/str[@name='class'] = 'solr.StopFilterFactory'");
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst[3]/str[@name='class'] = 'solr.LowerCaseFilterFactory'");
-    analyzerTests.add("/response/lst[@name='fieldType']/lst[@name='analyzer']/arr[@name='filters']/lst[4]/str[@name='class'] = 'solr.ASCIIFoldingFilterFactory'");
-    checkFieldTypeProps(expProps, 19, analyzerTests);        
-  }
-  
-  /**
-   * Helper function to check fieldType settings against a set of expected values.
-   */
-  protected void checkFieldTypeProps(Map<String,Object> expected, int expectedChildCount) {
-    checkFieldTypeProps(expected, expectedChildCount, null);
-  }
-  
-  protected void checkFieldTypeProps(Map<String,Object> expected, int expectedChildCount, List<String> addlTests) {
-    String fieldTypeName = (String)expected.get("name");
-    
-    List<String> tests = new ArrayList<>();
-    tests.add("count(/response/lst[@name='fieldType']) = 1");
-    tests.add("count(/response/lst[@name='fieldType']/*) = "+expectedChildCount);
-    tests.add("count(/response/lst[@name='fieldType']/arr[@name='fields']/*) = 0");
-    tests.add("count(/response/lst[@name='fieldType']/arr[@name='dynamicFields']/*) = 0");
-    for (Map.Entry<String,Object> next : expected.entrySet()) {
-      Object val = next.getValue();
-      String pathType = null;
-      if (val instanceof Boolean)
-        pathType = "bool";
-      else if (val instanceof String)
-        pathType = "str";
-      else
-        fail("Unexpected value type "+val.getClass().getName());
-      // NOTE: it seems like the fieldtypes endpoint only returns strings or booleans
-      
-      String xpath = 
-          "/response/lst[@name='fieldType']/"+pathType+"[@name='"+next.getKey()+"']";
-      tests.add(xpath+" = '"+val+"'");
-    }
-    
-    if (addlTests != null)
-      tests.addAll(addlTests);
-    
-    assertQ("/schema/fieldtypes/"+fieldTypeName+"?indent=on&wt=xml&showDefaults=true",
-        tests.toArray(new String[0]));
-  }
-  
-  /**
-   * Builds a map containing expected values for a field type created by this test. 
-   */
-  protected Map<String,Object> getExpectedProps(String name, String className, boolean indexed, boolean stored) {
-    Map<String,Object> map = new HashMap<>();
-    map.put("name", name);
-    map.put("class", className);
-    map.put("indexed", indexed);
-    map.put("stored", stored);      
-    map.put("docValues", false);
-    map.put("termVectors", false);
-    map.put("termPositions", false);
-    map.put("termOffsets", false);
-    map.put("omitNorms", true);
-    map.put("omitTermFreqAndPositions", true);
-    map.put("omitPositions", false);
-    map.put("storeOffsetsWithPositions", false);
-    map.put("multiValued", false);
-    map.put("tokenized", false);
-    return map;
-  }
-}


[08/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoBBoxTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoBBoxTest.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoBBoxTest.java
new file mode 100755
index 0000000..f5a148f
--- /dev/null
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoBBoxTest.java
@@ -0,0 +1,364 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class GeoBBoxTest {
+
+  protected final double DEGREES_TO_RADIANS = Math.PI / 180.0;
+
+  @Test
+  public void testBBoxDegenerate() {
+    GeoBBox box;
+    GeoConvexPolygon cp;
+    int relationship;
+    List<GeoPoint> points = new ArrayList<GeoPoint>();
+    points.add(new GeoPoint(PlanetModel.SPHERE, 24 * DEGREES_TO_RADIANS, -30 * DEGREES_TO_RADIANS));
+    points.add(new GeoPoint(PlanetModel.SPHERE, -11 * DEGREES_TO_RADIANS, 101 * DEGREES_TO_RADIANS));
+    points.add(new GeoPoint(PlanetModel.SPHERE, -49 * DEGREES_TO_RADIANS, -176 * DEGREES_TO_RADIANS));
+    GeoMembershipShape shape = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points, 0);
+    box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, -64 * DEGREES_TO_RADIANS, -64 * DEGREES_TO_RADIANS, -180 * DEGREES_TO_RADIANS, 180 * DEGREES_TO_RADIANS);
+    relationship = box.getRelationship(shape);
+    assertEquals(GeoArea.CONTAINS, relationship);
+    box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, -61.85 * DEGREES_TO_RADIANS, -67.5 * DEGREES_TO_RADIANS, -180 * DEGREES_TO_RADIANS, -168.75 * DEGREES_TO_RADIANS);
+    //System.out.println("Shape = " + shape + " Rect = " + box);
+    relationship = box.getRelationship(shape);
+    assertEquals(GeoArea.CONTAINS, relationship);
+  }
+
+  @Test
+  public void testBBoxPointWithin() {
+    GeoBBox box;
+    GeoPoint gp;
+
+    // Standard normal Rect box, not crossing dateline
+    box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -1.0, 1.0);
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 0.0);
+    assertTrue(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.1, 0.0);
+    assertFalse(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0);
+    assertFalse(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 1.1);
+    assertFalse(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -1.1);
+    assertFalse(box.isWithin(gp));
+    assertEquals(0.1,box.computeOutsideDistance(DistanceStyle.ARC,gp),1e-2);
+    assertEquals(0.1,box.computeOutsideDistance(DistanceStyle.NORMAL,gp),1e-2);
+    assertEquals(0.1,box.computeOutsideDistance(DistanceStyle.NORMAL,gp),1e-2);
+
+    // Standard normal Rect box, crossing dateline
+    box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, Math.PI - 1.0, -Math.PI + 1.0);
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI);
+    assertTrue(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.1, -Math.PI);
+    assertFalse(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, -Math.PI);
+    assertFalse(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI + 1.1);
+    assertFalse(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, (-Math.PI - 1.1) + Math.PI * 2.0);
+    assertFalse(box.isWithin(gp));
+
+    // Latitude zone rectangle
+    box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -Math.PI, Math.PI);
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI);
+    assertTrue(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.1, -Math.PI);
+    assertFalse(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, -Math.PI);
+    assertFalse(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI + 1.1);
+    assertTrue(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, (-Math.PI - 1.1) + Math.PI * 2.0);
+    assertTrue(box.isWithin(gp));
+
+    // World
+    box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, Math.PI);
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI);
+    assertTrue(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.1, -Math.PI);
+    assertTrue(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, -Math.PI);
+    assertTrue(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI + 1.1);
+    assertTrue(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, (-Math.PI - 1.1) + Math.PI * 2.0);
+    assertTrue(box.isWithin(gp));
+
+  }
+
+  @Test
+  public void testBBoxExpand() {
+    GeoBBox box;
+    GeoPoint gp;
+    // Standard normal Rect box, not crossing dateline
+    box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -1.0, 1.0);
+    box = box.expand(0.1);
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.05, 0.0);
+    assertTrue(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.15, 0.0);
+    assertFalse(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.25 - 0.05, 0.0);
+    assertTrue(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.25 - 0.15, 0.0);
+    assertFalse(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -1.05);
+    assertTrue(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -1.15);
+    assertFalse(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 1.05);
+    assertTrue(box.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 1.15);
+    assertFalse(box.isWithin(gp));
+  }
+
+  @Test
+  public void testBBoxBounds() {
+    GeoBBox c;
+    LatLonBounds b;
+    XYZBounds xyzb;
+    GeoArea solid;
+    GeoPoint point;
+    int relationship;
+    
+    c= GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.7570958596622309, -0.7458670829264561, -0.9566079379002148, 1.4802570961901191);
+    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE,0.10922258701604912,0.1248184603754517,-0.8172414690802067,0.9959041483215542,-0.6136586624726926,0.6821740363641521);
+    point = new GeoPoint(PlanetModel.SPHERE, 0.3719987557178081, 1.4529582778845198);
+    assertTrue(c.isWithin(point));
+    assertTrue(solid.isWithin(point));
+    relationship = solid.getRelationship(c);
+    assertTrue(relationship == GeoArea.OVERLAPS || relationship == GeoArea.CONTAINS || relationship == GeoArea.WITHIN);
+
+    c= GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.006607096847842122, -0.002828135860810422, -0.0012934461873348349, 0.006727418645092394);
+    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE,0.9999995988328008,1.0000000002328306,-0.0012934708508166816,0.006727393021214471,-0.002828157275369464,0.006607074060760007);
+    point = new GeoPoint(PlanetModel.SPHERE, -5.236470872437899E-4, 3.992578692654256E-4);
+    assertTrue(c.isWithin(point));
+    assertTrue(solid.isWithin(point));
+    relationship = solid.getRelationship(c);
+    assertTrue(relationship == GeoArea.OVERLAPS || relationship == GeoArea.CONTAINS || relationship == GeoArea.WITHIN);
+    
+    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.25, -Math.PI * 0.25, -1.0, 1.0);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(-1.0, b.getLeftLongitude(), 0.000001);
+    assertEquals(1.0, b.getRightLongitude(), 0.000001);
+    assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
+    assertEquals(Math.PI * 0.25, b.getMaxLatitude(), 0.000001);
+    assertEquals(0.382051, xyzb.getMinimumX(), 0.000001);
+    assertEquals(1.0, xyzb.getMaximumX(), 0.000001);
+    assertEquals(-0.841471, xyzb.getMinimumY(), 0.000001);
+    assertEquals(0.841471, xyzb.getMaximumY(), 0.000001);
+    assertEquals(-0.707107, xyzb.getMinimumZ(), 0.000001);
+    assertEquals(0.707107, xyzb.getMaximumZ(), 0.000001);
+    
+    GeoArea area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE,
+      xyzb.getMinimumX() - 2.0 * Vector.MINIMUM_RESOLUTION,
+      xyzb.getMaximumX() + 2.0 * Vector.MINIMUM_RESOLUTION,
+      xyzb.getMinimumY() - 2.0 * Vector.MINIMUM_RESOLUTION,
+      xyzb.getMaximumY() + 2.0 * Vector.MINIMUM_RESOLUTION,
+      xyzb.getMinimumZ() - 2.0 * Vector.MINIMUM_RESOLUTION,
+      xyzb.getMaximumZ() + 2.0 * Vector.MINIMUM_RESOLUTION);
+    assertEquals(GeoArea.WITHIN, area.getRelationship(c));
+
+    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -1.0, 1.0);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(-1.0, b.getLeftLongitude(), 0.000001);
+    assertEquals(1.0, b.getRightLongitude(), 0.000001);
+    assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
+    assertEquals(0.0, b.getMaxLatitude(), 0.000001);
+    assertEquals(0.382051, xyzb.getMinimumX(), 0.000001);
+    assertEquals(1.0, xyzb.getMaximumX(), 0.000001);
+    assertEquals(-0.841471, xyzb.getMinimumY(), 0.000001);
+    assertEquals(0.841471, xyzb.getMaximumY(), 0.000001);
+    assertEquals(-0.707107, xyzb.getMinimumZ(), 0.000001);
+    assertEquals(0.0, xyzb.getMaximumZ(), 0.000001);
+
+    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, 1.0, -1.0);
+
+    b = new LatLonBounds();
+    c.getBounds(b);
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    assertTrue(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    //assertEquals(1.0,b.getLeftLongitude(),0.000001);
+    //assertEquals(-1.0,b.getRightLongitude(),0.000001);
+    assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
+    assertEquals(0.0, b.getMaxLatitude(), 0.000001);
+    assertEquals(-1.0, xyzb.getMinimumX(), 0.000001);
+    assertEquals(0.540303, xyzb.getMaximumX(), 0.000001);
+    assertEquals(-1.0, xyzb.getMinimumY(), 0.000001);
+    assertEquals(1.0, xyzb.getMaximumY(), 0.000001);
+    assertEquals(-0.707107, xyzb.getMinimumZ(), 0.000001);
+    assertEquals(0.0, xyzb.getMaximumZ(), 0.000001);
+
+
+    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -1.0, 1.0);
+
+    b = new LatLonBounds();
+    c.getBounds(b);
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    assertTrue(b.checkNoLongitudeBound());
+    assertTrue(b.checkNoTopLatitudeBound());
+    assertTrue(b.checkNoBottomLatitudeBound());
+    //assertEquals(-1.0, b.getLeftLongitude(), 0.000001);
+    //assertEquals(1.0, b.getRightLongitude(), 0.000001);
+    assertEquals(0.0, xyzb.getMinimumX(), 0.000001);
+    assertEquals(1.0, xyzb.getMaximumX(), 0.000001);
+    assertEquals(-0.841471, xyzb.getMinimumY(), 0.000001);
+    assertEquals(0.841471, xyzb.getMaximumY(), 0.000001);
+    assertEquals(-1.0, xyzb.getMinimumZ(), 0.000001);
+    assertEquals(1.0, xyzb.getMaximumZ(), 0.000001);
+
+    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, 1.0, -1.0);
+
+    b = new LatLonBounds();
+    c.getBounds(b);
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    assertTrue(b.checkNoLongitudeBound());
+    assertTrue(b.checkNoTopLatitudeBound());
+    assertTrue(b.checkNoBottomLatitudeBound());
+    //assertEquals(1.0,b.getLeftLongitude(),0.000001);
+    //assertEquals(-1.0,b.getRightLongitude(),0.000001);
+    assertEquals(-1.0, xyzb.getMinimumX(), 0.000001);
+    assertEquals(0.540303, xyzb.getMaximumX(), 0.000001);
+    assertEquals(-1.0, xyzb.getMinimumY(), 0.000001);
+    assertEquals(1.0, xyzb.getMaximumY(), 0.000001);
+    assertEquals(-1.0, xyzb.getMinimumZ(), 0.000001);
+    assertEquals(1.0, xyzb.getMaximumZ(), 0.000001);
+
+    // Check wide variants of rectangle and longitude slice
+
+    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -Math.PI + 0.1, Math.PI - 0.1);
+
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertTrue(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    //assertEquals(-Math.PI+0.1,b.getLeftLongitude(),0.000001);
+    //assertEquals(Math.PI-0.1,b.getRightLongitude(),0.000001);
+    assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
+    assertEquals(0.0, b.getMaxLatitude(), 0.000001);
+
+    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, Math.PI - 0.1, -Math.PI + 0.1);
+
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(Math.PI - 0.1, b.getLeftLongitude(), 0.000001);
+    assertEquals(-Math.PI + 0.1, b.getRightLongitude(), 0.000001);
+    assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
+    assertEquals(0.0, b.getMaxLatitude(), 0.000001);
+
+    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI + 0.1, Math.PI - 0.1);
+
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertTrue(b.checkNoLongitudeBound());
+    assertTrue(b.checkNoTopLatitudeBound());
+    assertTrue(b.checkNoBottomLatitudeBound());
+    //assertEquals(-Math.PI+0.1,b.getLeftLongitude(),0.000001);
+    //assertEquals(Math.PI-0.1,b.getRightLongitude(),0.000001);
+
+    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, Math.PI - 0.1, -Math.PI + 0.1);
+
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertTrue(b.checkNoLongitudeBound());
+    assertTrue(b.checkNoTopLatitudeBound());
+    assertTrue(b.checkNoBottomLatitudeBound());
+    //assertEquals(Math.PI - 0.1, b.getLeftLongitude(), 0.000001);
+    //assertEquals(-Math.PI + 0.1, b.getRightLongitude(), 0.000001);
+
+    // Check latitude zone
+    c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 1.0, -1.0, -Math.PI, Math.PI);
+
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertTrue(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(-1.0, b.getMinLatitude(), 0.000001);
+    assertEquals(1.0, b.getMaxLatitude(), 0.000001);
+
+    // Now, combine a few things to test the bounds object
+    GeoBBox c1;
+    GeoBBox c2;
+
+    c1 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, 0.0);
+    c2 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI);
+
+    b = new LatLonBounds();
+    c1.getBounds(b);
+    c2.getBounds(b);
+    assertTrue(b.checkNoLongitudeBound());
+    assertTrue(b.checkNoTopLatitudeBound());
+    assertTrue(b.checkNoBottomLatitudeBound());
+
+    c1 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, 0.0);
+    c2 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI * 0.5);
+
+    b = new LatLonBounds();
+    c1.getBounds(b);
+    c2.getBounds(b);
+    assertTrue(b.checkNoLongitudeBound());
+    assertTrue(b.checkNoTopLatitudeBound());
+    assertTrue(b.checkNoBottomLatitudeBound());
+    //assertEquals(-Math.PI,b.getLeftLongitude(),0.000001);
+    //assertEquals(Math.PI*0.5,b.getRightLongitude(),0.000001);
+
+    c1 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI * 0.5, 0.0);
+    c2 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI);
+
+    b = new LatLonBounds();
+    c1.getBounds(b);
+    c2.getBounds(b);
+    assertTrue(b.checkNoLongitudeBound());
+    assertTrue(b.checkNoTopLatitudeBound());
+    assertTrue(b.checkNoBottomLatitudeBound());
+    //assertEquals(-Math.PI * 0.5,b.getLeftLongitude(),0.000001);
+    //assertEquals(Math.PI,b.getRightLongitude(),0.000001);
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoCircleTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoCircleTest.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoCircleTest.java
new file mode 100755
index 0000000..186bf4c
--- /dev/null
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoCircleTest.java
@@ -0,0 +1,410 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+import org.apache.lucene.util.LuceneTestCase;
+import org.junit.Test;
+
+public class GeoCircleTest extends LuceneTestCase {
+
+  @Test
+  public void testCircleDistance() {
+    GeoCircle c;
+    GeoPoint gp;
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.0, -0.5, 0.1);
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
+    assertEquals(Double.MAX_VALUE, c.computeDistance(DistanceStyle.ARC,gp), 0.0);
+    assertEquals(Double.MAX_VALUE, c.computeDistance(DistanceStyle.NORMAL,gp), 0.0);
+    assertEquals(Double.MAX_VALUE, c.computeDistance(DistanceStyle.NORMAL,gp), 0.0);
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
+    assertEquals(0.0, c.computeDistance(DistanceStyle.ARC,gp), 0.000001);
+    assertEquals(0.0, c.computeDistance(DistanceStyle.NORMAL,gp), 0.000001);
+    assertEquals(0.0, c.computeDistance(DistanceStyle.NORMAL,gp), 0.000001);
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.05, -0.5);
+    assertEquals(0.05, c.computeDistance(DistanceStyle.ARC,gp), 0.000001);
+    assertEquals(0.049995, c.computeDistance(DistanceStyle.LINEAR,gp), 0.000001);
+    assertEquals(0.049979, c.computeDistance(DistanceStyle.NORMAL,gp), 0.000001);
+  }
+
+  @Test
+  public void testCircleFullWorld() {
+    GeoCircle c;
+    GeoPoint gp;
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.0, -0.5, Math.PI);
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.0);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
+    assertTrue(c.isWithin(gp));
+    LatLonBounds b = new LatLonBounds();
+    c.getBounds(b);
+    assertTrue(b.checkNoLongitudeBound());
+    assertTrue(b.checkNoTopLatitudeBound());
+    assertTrue(b.checkNoBottomLatitudeBound());
+  }
+
+  @Test
+  public void testCirclePointWithin() {
+    GeoCircle c;
+    GeoPoint gp;
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.0, -0.5, 0.1);
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
+    assertFalse(c.isWithin(gp));
+    assertEquals(0.4,c.computeOutsideDistance(DistanceStyle.ARC,gp),1e-12);
+    assertEquals(0.12,c.computeOutsideDistance(DistanceStyle.NORMAL,gp),0.01);
+    assertEquals(0.4,c.computeOutsideDistance(DistanceStyle.LINEAR,gp),0.01);
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.0);
+    assertFalse(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
+    assertFalse(c.isWithin(gp));
+  }
+
+  @Test
+  public void testCircleBounds() {
+    GeoCircle c;
+    LatLonBounds b;
+    XYZBounds xyzb;
+    GeoArea area;
+    GeoPoint p1;
+    GeoPoint p2;
+    int relationship;
+
+    // ...
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84, -0.005931145568901605, -0.001942031539653079, 1.2991918568260272E-4);
+    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84, 1.001098377143621, 1.001100011578687, -0.00207467080358696, -0.0018136665346280983, -0.006067808248760161, -0.005807683665759485);
+    p1 = new GeoPoint(PlanetModel.WGS84, -0.00591253844632244, -0.0020069187259065093);
+    p2 = new GeoPoint(1.001099185736782, -0.0020091272069679327, -0.005919118245803968);
+    assertTrue(c.isWithin(p1));
+    assertTrue(area.isWithin(p1));
+    relationship = area.getRelationship(c);
+    assertTrue(relationship != GeoArea.DISJOINT);
+
+    // Twelfth BKD discovered failure
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84,-0.00824379317765984,-0.0011677469001838581,0.0011530035396910402);
+    p1 = new GeoPoint(PlanetModel.WGS84,-0.006505092992723671,0.007654282718327381);
+    p2 = new GeoPoint(1.0010681673665647,0.007662608264336381,-0.006512324005914593);
+    assertTrue(!c.isWithin(p1));
+    assertTrue(!c.isWithin(p2));
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84, 
+      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
+    relationship = area.getRelationship(c);
+    assertTrue(relationship == GeoArea.OVERLAPS || relationship == GeoArea.WITHIN);
+    // Point is actually outside the bounds, and outside the shape
+    assertTrue(!area.isWithin(p1));
+    // Approximate point the same
+    assertTrue(!area.isWithin(p2));
+    
+    // Eleventh BKD discovered failure
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE,-0.004431288600558495,-0.003687846671278374,1.704543429364245E-8);
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 
+      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
+    //System.err.println(area);
+    relationship = area.getRelationship(c);
+    assertTrue(GeoArea.WITHIN == relationship || GeoArea.OVERLAPS == relationship);
+
+    // Tenth BKD discovered failure
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84,-0.0018829770647349636,-0.001969499061382591,1.3045439293158305E-5);
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84, 
+      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
+    //System.err.println(area);
+    relationship = area.getRelationship(c);
+    assertTrue(GeoArea.WITHIN == relationship || GeoArea.OVERLAPS == relationship);
+
+    // Ninth BKD discovered failure
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE,-4.211990380885122E-5,-0.0022958453508173044,1.4318475623498535E-5);
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 
+      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
+    //System.err.println(area);
+    relationship = area.getRelationship(c);
+    assertTrue(GeoArea.WITHIN == relationship || GeoArea.OVERLAPS == relationship);
+    
+    // Eighth BKD discovered failure
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE,0.005321278689117842,-0.00216937368755372,1.5306034422500785E-4);
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 
+      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
+    //System.err.println(area);
+    relationship = area.getRelationship(c);
+    assertTrue(GeoArea.WITHIN == relationship || GeoArea.OVERLAPS == relationship);
+
+    // Seventh BKD discovered failure
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE,-0.0021627146783861745, -0.0017298167021592304,2.0818312293195752E-4);
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 
+      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
+    //System.err.println(area);
+    relationship = area.getRelationship(c);
+    assertTrue(GeoArea.WITHIN == relationship || GeoArea.OVERLAPS == relationship);
+
+    // Sixth BKD discovered failure
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84,-0.006450320645814321,0.004660694205115142,0.00489710732634323);
+    //xyzb = new XYZBounds();
+    //c.getBounds(xyzb);
+    //System.err.println("xmin="+xyzb.getMinimumX()+", xmax="+xyzb.getMaximumX()+",ymin="+xyzb.getMinimumY()+", ymax="+xyzb.getMaximumY()+",zmin="+xyzb.getMinimumZ()+", zmax="+xyzb.getMaximumZ());
+    //xmin=1.0010356621420726, xmax=1.0011141249179447,ymin=-2.5326643901354566E-4, ymax=0.009584741915757169,zmin=-0.011359874956269283, zmax=-0.0015549504447452225
+    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84,1.0010822580620098,1.0010945779732867,0.007079167343247293,0.007541006774427837,-0.0021855011220022575,-0.001896122718181518);
+    assertTrue(GeoArea.CONTAINS != area.getRelationship(c));
+    /*
+    p1 = new GeoPoint(1.0010893045436076,0.007380935180644008,-0.002140671370616495);
+    // This has a different bounding box, so we can't use it.
+    //p2 = new GeoPoint(PlanetModel.WGS84,-0.002164069780096702, 0.007505617500830066);
+    p2 = new GeoPoint(PlanetModel.WGS84,p1.getLatitude(),p1.getLongitude());
+    assertTrue(PlanetModel.WGS84.pointOnSurface(p2));
+    assertTrue(!c.isWithin(p2));
+    assertTrue(!area.isWithin(p2));
+    assertTrue(!c.isWithin(p1));
+    assertTrue(PlanetModel.WGS84.pointOnSurface(p1)); // This fails
+    assertTrue(!area.isWithin(p1)); // This fails
+    */
+    
+    // Fifth BKD discovered failure
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, -0.004282454525970269, -1.6739831367422277E-4, 1.959639723134033E-6);
+    assertTrue(c.isWithin(c.getEdgePoints()[0]));
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE,
+      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
+    assertTrue(GeoArea.WITHIN == area.getRelationship(c) || GeoArea.OVERLAPS == area.getRelationship(c));
+    
+    // Fourth BKD discovered failure
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, -0.0048795517261255, 0.004053904306995974, 5.93699764258874E-6);
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE,
+      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
+    assertTrue(GeoArea.WITHIN == area.getRelationship(c) || GeoArea.OVERLAPS == area.getRelationship(c));
+    
+    // Yet another test case from BKD
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84, 0.006229478708446979, 0.005570196723795424, 3.840276763694387E-5);
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84,
+      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
+    p1 = new GeoPoint(PlanetModel.WGS84, 0.006224927111830945, 0.005597367237251763);
+    p2 = new GeoPoint(1.0010836083810235, 0.005603490759433942, 0.006231850560862502);
+    assertTrue(PlanetModel.WGS84.pointOnSurface(p1));
+    //assertTrue(PlanetModel.WGS84.pointOnSurface(p2));
+    assertTrue(c.isWithin(p1));
+    assertTrue(c.isWithin(p2));
+    assertTrue(area.isWithin(p1));
+    assertTrue(area.isWithin(p2));
+    
+    // Another test case from BKD
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, -0.005955031040627789, -0.0029274772647399153, 1.601488279374338E-5);
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    area = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE,
+      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
+    
+    relationship = area.getRelationship(c);
+    assertTrue(relationship == GeoArea.WITHIN || relationship == GeoArea.OVERLAPS);
+    
+    // Test case from BKD
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, -0.765816119338, 0.991848766844, 0.8153163226330487);
+    p1 = new GeoPoint(0.7692262265236023, -0.055089298115534646, -0.6365973465711254);
+    assertTrue(c.isWithin(p1));
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    assertTrue(p1.x >= xyzb.getMinimumX() && p1.x <= xyzb.getMaximumX());
+    assertTrue(p1.y >= xyzb.getMinimumY() && p1.y <= xyzb.getMaximumY());
+    assertTrue(p1.z >= xyzb.getMinimumZ() && p1.z <= xyzb.getMaximumZ());
+    
+    // Vertical circle cases
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.0, -0.5, 0.1);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(-0.6, b.getLeftLongitude(), 0.000001);
+    assertEquals(-0.4, b.getRightLongitude(), 0.000001);
+    assertEquals(-0.1, b.getMinLatitude(), 0.000001);
+    assertEquals(0.1, b.getMaxLatitude(), 0.000001);
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.0, 0.5, 0.1);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(0.4, b.getLeftLongitude(), 0.000001);
+    assertEquals(0.6, b.getRightLongitude(), 0.000001);
+    assertEquals(-0.1, b.getMinLatitude(), 0.000001);
+    assertEquals(0.1, b.getMaxLatitude(), 0.000001);
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(-0.1, b.getLeftLongitude(), 0.000001);
+    assertEquals(0.1, b.getRightLongitude(), 0.000001);
+    assertEquals(-0.1, b.getMinLatitude(), 0.000001);
+    assertEquals(0.1, b.getMaxLatitude(), 0.000001);
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.0, Math.PI, 0.1);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(Math.PI - 0.1, b.getLeftLongitude(), 0.000001);
+    assertEquals(-Math.PI + 0.1, b.getRightLongitude(), 0.000001);
+    assertEquals(-0.1, b.getMinLatitude(), 0.000001);
+    assertEquals(0.1, b.getMaxLatitude(), 0.000001);
+    // Horizontal circle cases
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, Math.PI * 0.5, 0.0, 0.1);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertTrue(b.checkNoLongitudeBound());
+    assertTrue(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(Math.PI * 0.5 - 0.1, b.getMinLatitude(), 0.000001);
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0, 0.1);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertTrue(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertTrue(b.checkNoBottomLatitudeBound());
+    assertEquals(-Math.PI * 0.5 + 0.1, b.getMaxLatitude(), 0.000001);
+
+    // Now do a somewhat tilted plane, facing different directions.
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.01, 0.0, 0.1);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(0.11, b.getMaxLatitude(), 0.000001);
+    assertEquals(-0.09, b.getMinLatitude(), 0.000001);
+    assertEquals(-0.1, b.getLeftLongitude(), 0.00001);
+    assertEquals(0.1, b.getRightLongitude(), 0.00001);
+
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.01, Math.PI, 0.1);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(0.11, b.getMaxLatitude(), 0.000001);
+    assertEquals(-0.09, b.getMinLatitude(), 0.000001);
+    assertEquals(Math.PI - 0.1, b.getLeftLongitude(), 0.00001);
+    assertEquals(-Math.PI + 0.1, b.getRightLongitude(), 0.00001);
+
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.01, Math.PI * 0.5, 0.1);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(0.11, b.getMaxLatitude(), 0.000001);
+    assertEquals(-0.09, b.getMinLatitude(), 0.000001);
+    assertEquals(Math.PI * 0.5 - 0.1, b.getLeftLongitude(), 0.00001);
+    assertEquals(Math.PI * 0.5 + 0.1, b.getRightLongitude(), 0.00001);
+
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.01, -Math.PI * 0.5, 0.1);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(0.11, b.getMaxLatitude(), 0.000001);
+    assertEquals(-0.09, b.getMinLatitude(), 0.000001);
+    assertEquals(-Math.PI * 0.5 - 0.1, b.getLeftLongitude(), 0.00001);
+    assertEquals(-Math.PI * 0.5 + 0.1, b.getRightLongitude(), 0.00001);
+
+    // Slightly tilted, PI/4 direction.
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.01, Math.PI * 0.25, 0.1);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(0.11, b.getMaxLatitude(), 0.000001);
+    assertEquals(-0.09, b.getMinLatitude(), 0.000001);
+    assertEquals(Math.PI * 0.25 - 0.1, b.getLeftLongitude(), 0.00001);
+    assertEquals(Math.PI * 0.25 + 0.1, b.getRightLongitude(), 0.00001);
+
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.01, -Math.PI * 0.25, 0.1);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(0.11, b.getMaxLatitude(), 0.000001);
+    assertEquals(-0.09, b.getMinLatitude(), 0.000001);
+    assertEquals(-Math.PI * 0.25 - 0.1, b.getLeftLongitude(), 0.00001);
+    assertEquals(-Math.PI * 0.25 + 0.1, b.getRightLongitude(), 0.00001);
+
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, -0.01, Math.PI * 0.25, 0.1);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(0.09, b.getMaxLatitude(), 0.000001);
+    assertEquals(-0.11, b.getMinLatitude(), 0.000001);
+    assertEquals(Math.PI * 0.25 - 0.1, b.getLeftLongitude(), 0.00001);
+    assertEquals(Math.PI * 0.25 + 0.1, b.getRightLongitude(), 0.00001);
+
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, -0.01, -Math.PI * 0.25, 0.1);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(0.09, b.getMaxLatitude(), 0.000001);
+    assertEquals(-0.11, b.getMinLatitude(), 0.000001);
+    assertEquals(-Math.PI * 0.25 - 0.1, b.getLeftLongitude(), 0.00001);
+    assertEquals(-Math.PI * 0.25 + 0.1, b.getRightLongitude(), 0.00001);
+
+    // Now do a somewhat tilted plane.
+    c = GeoCircleFactory.makeGeoCircle(PlanetModel.SPHERE, 0.01, -0.5, 0.1);
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(0.11, b.getMaxLatitude(), 0.000001);
+    assertEquals(-0.09, b.getMinLatitude(), 0.000001);
+    assertEquals(-0.6, b.getLeftLongitude(), 0.00001);
+    assertEquals(-0.4, b.getRightLongitude(), 0.00001);
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoConvexPolygonTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoConvexPolygonTest.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoConvexPolygonTest.java
new file mode 100755
index 0000000..a6ca404
--- /dev/null
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoConvexPolygonTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class GeoConvexPolygonTest {
+
+
+  @Test
+  public void testPolygonPointWithin() {
+    GeoConvexPolygon c;
+    GeoPoint gp;
+    c = new GeoConvexPolygon(PlanetModel.SPHERE, -0.1, -0.5);
+    c.addPoint(0.0, -0.6, false);
+    c.addPoint(0.1, -0.5, false);
+    c.addPoint(0.0, -0.4, false);
+    c.done(false);
+    // Sample some points within
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.05, -0.5);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.05, -0.5);
+    assertTrue(c.isWithin(gp));
+    // Sample some nearby points outside, and compute distance-to-shape for them as well
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.65);
+    assertFalse(c.isWithin(gp));
+    assertEquals(0.05,c.computeOutsideDistance(DistanceStyle.ARC,gp),1e-12);
+    assertEquals(0.05,c.computeOutsideDistance(DistanceStyle.NORMAL,gp),1e-3);
+    assertEquals(0.05,c.computeOutsideDistance(DistanceStyle.LINEAR,gp),1e-3);
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.35);
+    assertFalse(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.15, -0.5);
+    assertFalse(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.15, -0.5);
+    assertFalse(c.isWithin(gp));
+    // Random points outside
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
+    assertFalse(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.0);
+    assertFalse(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
+    assertFalse(c.isWithin(gp));
+  }
+
+  @Test
+  public void testPolygonBounds() {
+    GeoConvexPolygon c;
+    LatLonBounds b;
+
+    c = new GeoConvexPolygon(PlanetModel.SPHERE, -0.1, -0.5);
+    c.addPoint(0.0, -0.6, false);
+    c.addPoint(0.1, -0.5, false);
+    c.addPoint(0.0, -0.4, false);
+    c.done(false);
+
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(-0.6, b.getLeftLongitude(), 0.000001);
+    assertEquals(-0.4, b.getRightLongitude(), 0.000001);
+    assertEquals(-0.1, b.getMinLatitude(), 0.000001);
+    assertEquals(0.1, b.getMaxLatitude(), 0.000001);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoModelTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoModelTest.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoModelTest.java
new file mode 100644
index 0000000..d5fcbdd
--- /dev/null
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoModelTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test basic plane functionality.
+ */
+public class GeoModelTest {
+
+  protected final static PlanetModel scaledModel = new PlanetModel(1.2,1.5);
+  
+  @Test
+  public void testBasicCircle() {
+    // The point of this test is just to make sure nothing blows up doing normal things with a quite non-spherical model
+    // Make sure that the north pole is in the circle, and south pole isn't
+    final GeoPoint northPole = new GeoPoint(scaledModel, Math.PI * 0.5, 0.0);
+    final GeoPoint southPole = new GeoPoint(scaledModel, -Math.PI * 0.5, 0.0);
+    final GeoPoint point1 = new GeoPoint(scaledModel, Math.PI * 0.25, 0.0);
+    final GeoPoint point2 = new GeoPoint(scaledModel, Math.PI * 0.125, 0.0);
+    
+    GeoCircle circle = new GeoStandardCircle(scaledModel, Math.PI * 0.5, 0.0, 0.01);
+    assertTrue(circle.isWithin(northPole));
+    assertFalse(circle.isWithin(southPole));
+    assertFalse(circle.isWithin(point1));
+    LatLonBounds bounds;
+    bounds = new LatLonBounds();
+    circle.getBounds(bounds);
+    assertTrue(bounds.checkNoLongitudeBound());
+    assertTrue(bounds.checkNoTopLatitudeBound());
+    assertFalse(bounds.checkNoBottomLatitudeBound());
+    assertEquals(Math.PI * 0.5 - 0.01, bounds.getMinLatitude(), 0.01);
+
+    circle = new GeoStandardCircle(scaledModel, Math.PI * 0.25, 0.0, 0.01);
+    assertTrue(circle.isWithin(point1));
+    assertFalse(circle.isWithin(northPole));
+    assertFalse(circle.isWithin(southPole));
+    bounds = new LatLonBounds();
+    circle.getBounds(bounds);
+    assertFalse(bounds.checkNoTopLatitudeBound());
+    assertFalse(bounds.checkNoLongitudeBound());
+    assertFalse(bounds.checkNoBottomLatitudeBound());
+    assertEquals(Math.PI * 0.25 + 0.01, bounds.getMaxLatitude(), 0.00001);
+    assertEquals(Math.PI * 0.25 - 0.01, bounds.getMinLatitude(), 0.00001);
+    assertEquals(-0.0125, bounds.getLeftLongitude(), 0.0001);
+    assertEquals(0.0125, bounds.getRightLongitude(), 0.0001);
+
+    circle = new GeoStandardCircle(scaledModel, Math.PI * 0.125, 0.0, 0.01);
+    assertTrue(circle.isWithin(point2));
+    assertFalse(circle.isWithin(northPole));
+    assertFalse(circle.isWithin(southPole));
+    bounds = new LatLonBounds();
+    circle.getBounds(bounds);
+    assertFalse(bounds.checkNoLongitudeBound());
+    assertFalse(bounds.checkNoTopLatitudeBound());
+    assertFalse(bounds.checkNoBottomLatitudeBound());
+    // Symmetric, as expected
+    assertEquals(Math.PI * 0.125 - 0.01, bounds.getMinLatitude(), 0.00001);
+    assertEquals(Math.PI * 0.125 + 0.01, bounds.getMaxLatitude(), 0.00001);
+    assertEquals(-0.0089, bounds.getLeftLongitude(), 0.0001);
+    assertEquals(0.0089, bounds.getRightLongitude(), 0.0001);
+
+  }
+
+  @Test
+  public void testBasicRectangle() {
+    final GeoBBox bbox = GeoBBoxFactory.makeGeoBBox(scaledModel, 1.0, 0.0, 0.0, 1.0);
+    final GeoPoint insidePoint = new GeoPoint(scaledModel, 0.5, 0.5);
+    assertTrue(bbox.isWithin(insidePoint));
+    final GeoPoint topOutsidePoint = new GeoPoint(scaledModel, 1.01, 0.5);
+    assertFalse(bbox.isWithin(topOutsidePoint));
+    final GeoPoint bottomOutsidePoint = new GeoPoint(scaledModel, -0.01, 0.5);
+    assertFalse(bbox.isWithin(bottomOutsidePoint));
+    final GeoPoint leftOutsidePoint = new GeoPoint(scaledModel, 0.5, -0.01);
+    assertFalse(bbox.isWithin(leftOutsidePoint));
+    final GeoPoint rightOutsidePoint = new GeoPoint(scaledModel, 0.5, 1.01);
+    assertFalse(bbox.isWithin(rightOutsidePoint));
+    final LatLonBounds bounds = new LatLonBounds();
+    bbox.getBounds(bounds);
+    assertFalse(bounds.checkNoLongitudeBound());
+    assertFalse(bounds.checkNoTopLatitudeBound());
+    assertFalse(bounds.checkNoBottomLatitudeBound());
+    assertEquals(1.0, bounds.getMaxLatitude(), 0.00001);
+    assertEquals(0.0, bounds.getMinLatitude(), 0.00001);
+    assertEquals(1.0, bounds.getRightLongitude(), 0.00001);
+    assertEquals(0.0, bounds.getLeftLongitude(), 0.00001);
+  }
+  
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoPathTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoPathTest.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoPathTest.java
new file mode 100755
index 0000000..3746069
--- /dev/null
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoPathTest.java
@@ -0,0 +1,270 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+import org.junit.Test;
+
+import static java.lang.Math.toRadians;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class GeoPathTest {
+
+  @Test
+  public void testPathDistance() {
+    // Start with a really simple case
+    GeoPath p;
+    GeoPoint gp;
+    p = new GeoPath(PlanetModel.SPHERE, 0.1);
+    p.addPoint(0.0, 0.0);
+    p.addPoint(0.0, 0.1);
+    p.addPoint(0.0, 0.2);
+    p.done();
+    gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.15);
+    assertEquals(Double.MAX_VALUE, p.computeDistance(DistanceStyle.ARC,gp), 0.0);
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.05, 0.15);
+    assertEquals(0.15 + 0.05, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.12);
+    assertEquals(0.12 + 0.0, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.15, 0.05);
+    assertEquals(Double.MAX_VALUE, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.25);
+    assertEquals(0.20 + 0.05, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.05);
+    assertEquals(0.0 + 0.05, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
+
+    // Compute path distances now
+    p = new GeoPath(PlanetModel.SPHERE, 0.1);
+    p.addPoint(0.0, 0.0);
+    p.addPoint(0.0, 0.1);
+    p.addPoint(0.0, 0.2);
+    p.done();
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.05, 0.15);
+    assertEquals(0.15 + 0.05, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.12);
+    assertEquals(0.12, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
+
+    // Now try a vertical path, and make sure distances are as expected
+    p = new GeoPath(PlanetModel.SPHERE, 0.1);
+    p.addPoint(-Math.PI * 0.25, -0.5);
+    p.addPoint(Math.PI * 0.25, -0.5);
+    p.done();
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
+    assertEquals(Double.MAX_VALUE, p.computeDistance(DistanceStyle.ARC,gp), 0.0);
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -1.0);
+    assertEquals(Double.MAX_VALUE, p.computeDistance(DistanceStyle.ARC,gp), 0.0);
+    gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.25 + 0.05, -0.5);
+    assertEquals(Math.PI * 0.5 + 0.05, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
+    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.25 - 0.05, -0.5);
+    assertEquals(0.0 + 0.05, p.computeDistance(DistanceStyle.ARC,gp), 0.000001);
+  }
+
+  @Test
+  public void testPathPointWithin() {
+    // Tests whether we can properly detect whether a point is within a path or not
+    GeoPath p;
+    GeoPoint gp;
+    p = new GeoPath(PlanetModel.SPHERE, 0.1);
+    // Build a diagonal path crossing the equator
+    p.addPoint(-0.2, -0.2);
+    p.addPoint(0.2, 0.2);
+    p.done();
+    // Test points on the path
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.2, -0.2);
+    assertTrue(p.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
+    assertTrue(p.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.1, 0.1);
+    assertTrue(p.isWithin(gp));
+    // Test points off the path
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.2, 0.2);
+    assertFalse(p.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0);
+    assertFalse(p.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.2, -0.2);
+    assertFalse(p.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
+    assertFalse(p.isWithin(gp));
+    // Repeat the test, but across the terminator
+    p = new GeoPath(PlanetModel.SPHERE, 0.1);
+    // Build a diagonal path crossing the equator
+    p.addPoint(-0.2, Math.PI - 0.2);
+    p.addPoint(0.2, -Math.PI + 0.2);
+    p.done();
+    // Test points on the path
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.2, Math.PI - 0.2);
+    assertTrue(p.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
+    assertTrue(p.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.1, -Math.PI + 0.1);
+    assertTrue(p.isWithin(gp));
+    // Test points off the path
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.2, -Math.PI + 0.2);
+    assertFalse(p.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0);
+    assertFalse(p.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.2, Math.PI - 0.2);
+    assertFalse(p.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
+    assertFalse(p.isWithin(gp));
+
+  }
+
+  @Test
+  public void testGetRelationship() {
+    GeoArea rect;
+    GeoPath p;
+    GeoPath c;
+    GeoPoint point;
+    GeoPoint pointApprox;
+    int relationship;
+    GeoArea area;
+    PlanetModel planetModel;
+    
+    planetModel = new PlanetModel(1.151145876105594, 0.8488541238944061);
+    c = new GeoPath(planetModel, 0.008726646259971648);
+    c.addPoint(-0.6925658899376476, 0.6316613927914589);
+    c.addPoint(0.27828548161836364, 0.6785795524104564);
+    c.done();
+    point = new GeoPoint(planetModel,-0.49298555067758226, 0.9892440995026406);
+    pointApprox = new GeoPoint(0.5110940362119821, 0.7774603209946239, -0.49984312299556544);
+    area = GeoAreaFactory.makeGeoArea(planetModel, 0.49937141144985997, 0.5161765426256085, 0.3337218719537796,0.8544419570901649, -0.6347692823688085, 0.3069696588119369);
+    assertTrue(!c.isWithin(point));
+    
+    // Start by testing the basic kinds of relationship, increasing in order of difficulty.
+
+    p = new GeoPath(PlanetModel.SPHERE, 0.1);
+    p.addPoint(-0.3, -0.3);
+    p.addPoint(0.3, 0.3);
+    p.done();
+    // Easiest: The path is wholly contains the georect
+    rect = new GeoRectangle(PlanetModel.SPHERE, 0.05, -0.05, -0.05, 0.05);
+    assertEquals(GeoArea.CONTAINS, rect.getRelationship(p));
+    // Next easiest: Some endpoints of the rectangle are inside, and some are outside.
+    rect = new GeoRectangle(PlanetModel.SPHERE, 0.05, -0.05, -0.05, 0.5);
+    assertEquals(GeoArea.OVERLAPS, rect.getRelationship(p));
+    // Now, all points are outside, but the figures intersect
+    rect = new GeoRectangle(PlanetModel.SPHERE, 0.05, -0.05, -0.5, 0.5);
+    assertEquals(GeoArea.OVERLAPS, rect.getRelationship(p));
+    // Finally, all points are outside, and the figures *do not* intersect
+    rect = new GeoRectangle(PlanetModel.SPHERE, 0.5, -0.5, -0.5, 0.5);
+    assertEquals(GeoArea.WITHIN, rect.getRelationship(p));
+    // Check that segment edge overlap detection works
+    rect = new GeoRectangle(PlanetModel.SPHERE, 0.1, 0.0, -0.1, 0.0);
+    assertEquals(GeoArea.OVERLAPS, rect.getRelationship(p));
+    rect = new GeoRectangle(PlanetModel.SPHERE, 0.2, 0.1, -0.2, -0.1);
+    assertEquals(GeoArea.DISJOINT, rect.getRelationship(p));
+    // Check if overlap at endpoints behaves as expected next
+    rect = new GeoRectangle(PlanetModel.SPHERE, 0.5, -0.5, -0.5, -0.35);
+    assertEquals(GeoArea.OVERLAPS, rect.getRelationship(p));
+    rect = new GeoRectangle(PlanetModel.SPHERE, 0.5, -0.5, -0.5, -0.45);
+    assertEquals(GeoArea.DISJOINT, rect.getRelationship(p));
+
+  }
+
+  @Test
+  public void testPathBounds() {
+    GeoPath c;
+    LatLonBounds b;
+    XYZBounds xyzb;
+    GeoPoint point;
+    int relationship;
+    GeoArea area;
+    PlanetModel planetModel;
+    
+    planetModel = new PlanetModel(0.751521665790406,1.248478334209594);
+    c = new GeoPath(planetModel, 0.7504915783575618);
+    c.addPoint(0.10869761172400265, 0.08895880215465272);
+    c.addPoint(0.22467878641991612, 0.10972973084229565);
+    c.addPoint(-0.7398772468744732, -0.4465812941383364);
+    c.addPoint(-0.18462055300079366, -0.6713857796763727);
+    c.done();
+    point = new GeoPoint(planetModel,-0.626645355125733,-1.409304625439381);
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    area = GeoAreaFactory.makeGeoArea(planetModel,
+      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
+    relationship = area.getRelationship(c);
+    assertTrue(relationship == GeoArea.WITHIN || relationship == GeoArea.OVERLAPS);
+    assertTrue(area.isWithin(point));
+    // No longer true due to fixed GeoPath waypoints.
+    //assertTrue(c.isWithin(point));
+    
+    c = new GeoPath(PlanetModel.WGS84, 0.6894050545377601);
+    c.addPoint(-0.0788176065762948, 0.9431251741731624);
+    c.addPoint(0.510387871458147, 0.5327078872484678);
+    c.addPoint(-0.5624521609859962, 1.5398841746888388);
+    c.addPoint(-0.5025171434638661, -0.5895998642788894);
+    c.done();
+    point = new GeoPoint(PlanetModel.WGS84, 0.023652082107211682, 0.023131910152748437);
+    //System.err.println("Point.x = "+point.x+"; point.y="+point.y+"; point.z="+point.z);
+    assertTrue(c.isWithin(point));
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84,
+      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
+    //System.err.println("minx="+xyzb.getMinimumX()+" maxx="+xyzb.getMaximumX()+" miny="+xyzb.getMinimumY()+" maxy="+xyzb.getMaximumY()+" minz="+xyzb.getMinimumZ()+" maxz="+xyzb.getMaximumZ());
+    //System.err.println("point.x="+point.x+" point.y="+point.y+" point.z="+point.z);
+    relationship = area.getRelationship(c);
+    assertTrue(relationship == GeoArea.WITHIN || relationship == GeoArea.OVERLAPS);
+    assertTrue(area.isWithin(point));
+    
+    c = new GeoPath(PlanetModel.WGS84, 0.7766715171374766);
+    c.addPoint(-0.2751718361148076, -0.7786721269011477);
+    c.addPoint(0.5728375851539309, -1.2700115736820465);
+    c.done();
+    point = new GeoPoint(PlanetModel.WGS84, -0.01580760332365284, -0.03956004622490505);
+    assertTrue(c.isWithin(point));
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84,
+      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
+    //System.err.println("minx="+xyzb.getMinimumX()+" maxx="+xyzb.getMaximumX()+" miny="+xyzb.getMinimumY()+" maxy="+xyzb.getMaximumY()+" minz="+xyzb.getMinimumZ()+" maxz="+xyzb.getMaximumZ());
+    //System.err.println("point.x="+point.x+" point.y="+point.y+" point.z="+point.z);
+    relationship = area.getRelationship(c);
+    assertTrue(relationship == GeoArea.WITHIN || relationship == GeoArea.OVERLAPS);
+    assertTrue(area.isWithin(point));
+
+    c = new GeoPath(PlanetModel.SPHERE, 0.1);
+    c.addPoint(-0.3, -0.3);
+    c.addPoint(0.3, 0.3);
+    c.done();
+
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(-0.4046919, b.getLeftLongitude(), 0.000001);
+    assertEquals(0.4046919, b.getRightLongitude(), 0.000001);
+    assertEquals(-0.3999999, b.getMinLatitude(), 0.000001);
+    assertEquals(0.3999999, b.getMaxLatitude(), 0.000001);
+
+  }
+
+  @Test
+  public void testCoLinear() {
+    // p1: (12,-90), p2: (11, -55), (129, -90)
+    GeoPath p = new GeoPath(PlanetModel.SPHERE, 0.1);
+    p.addPoint(toRadians(-90), toRadians(12));//south pole
+    p.addPoint(toRadians(-55), toRadians(11));
+    p.addPoint(toRadians(-90), toRadians(129));//south pole again
+    p.done();//at least test this doesn't bomb like it used too -- LUCENE-6520
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoPointTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoPointTest.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoPointTest.java
new file mode 100644
index 0000000..ed17928
--- /dev/null
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoPointTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+import org.apache.lucene.util.LuceneTestCase;
+import org.junit.Test;
+
+import static com.carrotsearch.randomizedtesting.RandomizedTest.randomFloat;
+
+/**
+ * Test basic GeoPoint functionality.
+ */
+public class GeoPointTest extends LuceneTestCase {
+  static final double DEGREES_TO_RADIANS =  Math.PI / 180;
+
+  @Test
+  public void testConversion() {
+    testPointRoundTrip(PlanetModel.SPHERE, 90 * DEGREES_TO_RADIANS, 0, 1e-6);
+    testPointRoundTrip(PlanetModel.SPHERE, -90 * DEGREES_TO_RADIANS, 0, 1e-6);
+    testPointRoundTrip(PlanetModel.WGS84, 90 * DEGREES_TO_RADIANS, 0, 1e-6);
+    testPointRoundTrip(PlanetModel.WGS84, -90 * DEGREES_TO_RADIANS, 0, 1e-6);
+
+    final int times = atLeast(100);
+    for (int i = 0; i < times; i++) {
+      final double pLat = (randomFloat() * 180.0 - 90.0) * DEGREES_TO_RADIANS;
+      final double pLon = (randomFloat() * 360.0 - 180.0) * DEGREES_TO_RADIANS;
+      testPointRoundTrip(PlanetModel.SPHERE, pLat, pLon, 1e-6);//1e-6 since there's a square root in there (Karl says)
+      testPointRoundTrip(PlanetModel.WGS84, pLat, pLon, 1e-6);
+    }
+  }
+
+  protected void testPointRoundTrip(PlanetModel planetModel, double pLat, double pLon, double epsilon) {
+    final GeoPoint p1 = new GeoPoint(planetModel, pLat, pLon);
+    // In order to force the reverse conversion, we have to construct a geopoint from just x,y,z
+    final GeoPoint p2 = new GeoPoint(p1.x, p1.y, p1.z);
+    // Now, construct the final point based on getLatitude() and getLongitude()
+    final GeoPoint p3 = new GeoPoint(planetModel, p2.getLatitude(), p2.getLongitude());
+    double dist = p1.arcDistance(p3);
+    assertEquals(0, dist, epsilon);
+  }
+
+  @Test
+  public void testSurfaceDistance() {
+    final int times = atLeast(100);
+    for (int i = 0; i < times; i++) {
+      final double p1Lat = (randomFloat() * 180.0 - 90.0) * DEGREES_TO_RADIANS;
+      final double p1Lon = (randomFloat() * 360.0 - 180.0) * DEGREES_TO_RADIANS;
+      final double p2Lat = (randomFloat() * 180.0 - 90.0) * DEGREES_TO_RADIANS;
+      final double p2Lon = (randomFloat() * 360.0 - 180.0) * DEGREES_TO_RADIANS;
+      final GeoPoint p1 = new GeoPoint(PlanetModel.SPHERE, p1Lat, p1Lon);
+      final GeoPoint p2 = new GeoPoint(PlanetModel.SPHERE, p2Lat, p2Lon);
+      final double arcDistance = p1.arcDistance(p2);
+      // Compute ellipsoid distance; it should agree for a sphere
+      final double surfaceDistance = PlanetModel.SPHERE.surfaceDistance(p1,p2);
+      assertEquals(arcDistance, surfaceDistance, 1e-6);
+    }
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testBadLatLon() {
+    new GeoPoint(PlanetModel.SPHERE, 50.0, 32.2);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoPolygonTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoPolygonTest.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoPolygonTest.java
new file mode 100755
index 0000000..d9b220d
--- /dev/null
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/GeoPolygonTest.java
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class GeoPolygonTest {
+
+
+  @Test
+  public void testPolygonPointWithin() {
+    GeoMembershipShape c;
+    GeoPoint gp;
+    List<GeoPoint> points;
+
+    points = new ArrayList<GeoPoint>();
+    points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.5));
+    points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.6));
+    points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.5));
+    points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.4));
+
+    c = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points, 0);
+    // Sample some points within
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.05, -0.5);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.05, -0.5);
+    assertTrue(c.isWithin(gp));
+    // Sample some nearby points outside
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.65);
+    assertFalse(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.35);
+    assertFalse(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.15, -0.5);
+    assertFalse(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.15, -0.5);
+    assertFalse(c.isWithin(gp));
+    // Random points outside
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
+    assertFalse(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.0);
+    assertFalse(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
+    assertFalse(c.isWithin(gp));
+
+    points = new ArrayList<GeoPoint>();
+    points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.5));
+    points.add(new GeoPoint(PlanetModel.SPHERE, -0.01, -0.6));
+    points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.7));
+    points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.8));
+    points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.7));
+    points.add(new GeoPoint(PlanetModel.SPHERE, 0.01, -0.6));
+    points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.5));
+    points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.4));
+        
+        /*
+        System.out.println("Points: ");
+        for (GeoPoint p : points) {
+            System.out.println(" "+p);
+        }
+        */
+
+    c = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points, 0);
+    // Sample some points within
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.05, -0.5);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.05, -0.5);
+    assertTrue(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.7);
+    assertTrue(c.isWithin(gp));
+    // Sample some nearby points outside
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.35);
+    assertFalse(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, -0.15, -0.5);
+    assertFalse(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.15, -0.5);
+    assertFalse(c.isWithin(gp));
+    // Random points outside
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
+    assertFalse(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.0);
+    assertFalse(c.isWithin(gp));
+    gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
+    assertFalse(c.isWithin(gp));
+
+  }
+
+  @Test
+  public void testPolygonBounds() {
+    GeoMembershipShape c;
+    LatLonBounds b;
+    List<GeoPoint> points;
+    XYZBounds xyzb;
+    GeoPoint point;
+    GeoArea area;
+    
+    // BKD failure
+    points = new ArrayList<GeoPoint>();
+    points.add(new GeoPoint(PlanetModel.WGS84, -0.36716183577912814, 1.4836349969188696));
+    points.add(new GeoPoint(PlanetModel.WGS84, 0.7846038240742979, -0.02743348424931823));
+    points.add(new GeoPoint(PlanetModel.WGS84, -0.7376479402362607, -0.5072961758807019));
+    points.add(new GeoPoint(PlanetModel.WGS84, -0.3760415907667887, 1.4970455334565513));
+    
+    c = GeoPolygonFactory.makeGeoPolygon(PlanetModel.WGS84, points, 1);
+    
+    point = new GeoPoint(PlanetModel.WGS84, -0.01580760332365284, -0.03956004622490505);
+    assertTrue(c.isWithin(point));
+    xyzb = new XYZBounds();
+    c.getBounds(xyzb);
+    area = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84,
+      xyzb.getMinimumX(), xyzb.getMaximumX(), xyzb.getMinimumY(), xyzb.getMaximumY(), xyzb.getMinimumZ(), xyzb.getMaximumZ());
+    assertTrue(area.isWithin(point));
+    
+    points = new ArrayList<GeoPoint>();
+    points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.5));
+    points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.6));
+    points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.5));
+    points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.4));
+
+    c = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points, 0);
+
+    b = new LatLonBounds();
+    c.getBounds(b);
+    assertFalse(b.checkNoLongitudeBound());
+    assertFalse(b.checkNoTopLatitudeBound());
+    assertFalse(b.checkNoBottomLatitudeBound());
+    assertEquals(-0.6, b.getLeftLongitude(), 0.000001);
+    assertEquals(-0.4, b.getRightLongitude(), 0.000001);
+    assertEquals(-0.1, b.getMinLatitude(), 0.000001);
+    assertEquals(0.1, b.getMaxLatitude(), 0.000001);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/PlaneTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/PlaneTest.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/PlaneTest.java
new file mode 100644
index 0000000..91bd0c3
--- /dev/null
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/PlaneTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test basic plane functionality.
+ */
+public class PlaneTest {
+
+
+  @Test
+  public void testIdenticalPlanes() {
+    final GeoPoint p = new GeoPoint(PlanetModel.SPHERE, 0.123, -0.456);
+    final Plane plane1 = new Plane(p, 0.0);
+    final Plane plane2 = new Plane(p, 0.0);
+    assertTrue(plane1.isNumericallyIdentical(plane2));
+    final Plane plane3 = new Plane(p, 0.1);
+    assertFalse(plane1.isNumericallyIdentical(plane3));
+    final Vector v1 = new Vector(0.1, -0.732, 0.9);
+    final double constant = 0.432;
+    final Vector v2 = new Vector(v1.x * constant, v1.y * constant, v1.z * constant);
+    final Plane p1 = new Plane(v1, 0.2);
+    final Plane p2 = new Plane(v2, 0.2 * constant);
+    assertTrue(p1.isNumericallyIdentical(p2));
+  }
+
+  @Test
+  public void testInterpolation() {
+    // [X=0.35168818443386646, Y=-0.19637966197066342, Z=0.9152870857244183],
+    // [X=0.5003343189532654, Y=0.522128543226148, Z=0.6906861469771293],
+
+    final GeoPoint start = new GeoPoint(0.35168818443386646, -0.19637966197066342, 0.9152870857244183);
+    final GeoPoint end = new GeoPoint(0.5003343189532654, 0.522128543226148, 0.6906861469771293);
+
+    // [A=-0.6135342247741855, B=0.21504338363863665, C=0.28188192383666794, D=0.0, side=-1.0] internal? false;
+    final Plane p = new Plane(-0.6135342247741855, 0.21504338363863665, 0.28188192383666794, 0.0);
+
+    final GeoPoint[] points = p.interpolate(start, end, new double[]{0.25, 0.50, 0.75});
+
+    for (GeoPoint point : points) {
+      assertTrue(p.evaluateIsZero(point));
+    }
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/XYZSolidTest.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/XYZSolidTest.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/XYZSolidTest.java
new file mode 100644
index 0000000..98c616e
--- /dev/null
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/XYZSolidTest.java
@@ -0,0 +1,220 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+import org.apache.lucene.util.LuceneTestCase;
+import org.junit.Test;
+
+public class XYZSolidTest extends LuceneTestCase {
+
+  @Test
+  public void testNonDegenerateRelationships() {
+    XYZSolid s;
+    GeoShape shape;
+    // Something bigger than the world
+    s = new StandardXYZSolid(PlanetModel.SPHERE, -2.0, 2.0, -2.0, 2.0, -2.0, 2.0);
+    // Any shape, except whole world, should be within.
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.WITHIN, s.getRelationship(shape));
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    // An XYZSolid represents a surface shape, which when larger than the world is in fact
+    // the entire world, so it should overlap the world.
+    assertEquals(GeoArea.OVERLAPS, s.getRelationship(shape));
+
+    // Something overlapping the world on only one side
+    s = new StandardXYZSolid(PlanetModel.SPHERE, -2.0, 0.0, -2.0, 2.0, -2.0, 2.0);
+    // Some things should be disjoint...
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.DISJOINT, s.getRelationship(shape));
+    // And, some things should be within... 
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI, 0.1);
+    assertEquals(GeoArea.WITHIN, s.getRelationship(shape));
+    // And, some things should overlap.
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI * 0.5, 0.1);
+    assertEquals(GeoArea.OVERLAPS, s.getRelationship(shape));
+
+    // Partial world should be contained by GeoWorld object...
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    assertEquals(GeoArea.CONTAINS, s.getRelationship(shape));
+    
+    // Something inside the world
+    s = new StandardXYZSolid(PlanetModel.SPHERE, -0.1, 0.1, -0.1, 0.1, -0.1, 0.1);
+    // All shapes should be disjoint
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.DISJOINT, s.getRelationship(shape));
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    assertEquals(GeoArea.DISJOINT, s.getRelationship(shape));
+    
+  }
+
+  @Test
+  public void testDegenerateRelationships() {
+    GeoArea solid;
+    GeoShape shape;
+    
+    // Basic test of the factory method - non-degenerate
+    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, -2.0, 2.0, -2.0, 2.0, -2.0, 2.0);
+    // Any shape, except whole world, should be within.
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.WITHIN, solid.getRelationship(shape));
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    // An XYZSolid represents a surface shape, which when larger than the world is in fact
+    // the entire world, so it should overlap the world.
+    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
+
+    // Build a degenerate point, not on sphere
+    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+    // disjoint with everything?
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+
+    // Build a degenerate point that IS on the sphere
+    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0);
+    // inside everything that it touches?
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+
+    // Build a shape degenerate in (x,y), which has no points on sphere
+    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, 0.0, 0.0, -0.1, 0.1);
+    // disjoint with everything?
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+
+    // Build a shape degenerate in (x,y) which has one point on sphere
+    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, 0.0, 0.0, -0.1, 1.1);
+    // inside everything that it touches?
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, Math.PI * 0.5, 0.0, 0.1);
+    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+
+    // Build a shape degenerate in (x,y) which has two points on sphere
+    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, 0.0, 0.0, -1.1, 1.1);
+    // inside everything that it touches?
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, Math.PI * 0.5, 0.0, 0.1);
+    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0, 0.1);
+    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
+    
+    // Build a shape degenerate in (x,z), which has no points on sphere
+    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -0.1, 0.1, 0.0, 0.0);
+    // disjoint with everything?
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+
+    // Build a shape degenerate in (x,z) which has one point on sphere
+    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -0.1, 1.1, 0.0, 0.0);
+    // inside everything that it touches?
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI * 0.5, 0.1);
+    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, -Math.PI * 0.5, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+
+    // Build a shape degenerate in (x,y) which has two points on sphere
+    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -1.1, 1.1, 0.0, 0.0);
+    // inside everything that it touches?
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI * 0.5, 0.1);
+    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, -Math.PI * 0.5, 0.1);
+    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
+
+    // MHL for y-z check
+    
+    // Build a shape that is degenerate in x, which has zero points intersecting sphere
+    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -0.1, 0.1, -0.1, 0.1);
+    // disjoint with everything?
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+
+    // Build a shape that is degenerate in x, which has zero points intersecting sphere, second variation
+    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -0.1, 0.1, 1.1, 1.2);
+    // disjoint with everything?
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+
+    // Build a shape that is disjoint in X but intersects sphere in a complete circle
+    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, -1.1, 1.1, -1.1, 1.1);
+    // inside everything that it touches?
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI * 0.5, 0.1);
+    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, -Math.PI * 0.5, 0.1);
+    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, Math.PI * 0.5, 0.0, 0.1);
+    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0, 0.1);
+    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
+
+    // Build a shape that is disjoint in X but intersects sphere in a half circle in Y
+    solid = GeoAreaFactory.makeGeoArea(PlanetModel.SPHERE, 0.0, 0.0, 0.0, 1.1, -1.1, 1.1);
+    // inside everything that it touches?
+    shape = new GeoWorld(PlanetModel.SPHERE);
+    assertEquals(GeoArea.CONTAINS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, Math.PI * 0.5, 0.1);
+    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, 0.0, -Math.PI * 0.5, 0.1);
+    assertEquals(GeoArea.DISJOINT, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, Math.PI * 0.5, 0.0, 0.1);
+    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
+    shape = new GeoStandardCircle(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0, 0.1);
+    assertEquals(GeoArea.OVERLAPS, solid.getRelationship(shape));
+
+    // MHL for degenerate Y
+    // MHL for degenerate Z
+    
+  }
+  
+}


[26/50] [abbrv] lucene-solr git commit: Merge branch 'SOLR-8782'

Posted by no...@apache.org.
Merge branch 'SOLR-8782'


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

Branch: refs/heads/apiv2
Commit: 406a1635c11919cbd167eb5ea87461472dbc8d53
Parents: a0a571c 5b7be9d
Author: Alan Woodward <ro...@apache.org>
Authored: Tue Mar 8 10:53:39 2016 +0000
Committer: Alan Woodward <ro...@apache.org>
Committed: Tue Mar 8 10:53:39 2016 +0000

----------------------------------------------------------------------
 solr/CHANGES.txt                                |   4 +
 .../configsets/cloud-minimal/conf/schema.xml    |  32 +
 .../cloud-minimal/conf/solrconfig.xml           |  48 ++
 .../CollectionsAPIAsyncDistributedZkTest.java   | 174 ++---
 .../solr/security/BasicAuthIntegrationTest.java |   2 +-
 .../solrj/request/CollectionAdminRequest.java   | 691 +++++++++++++------
 6 files changed, 622 insertions(+), 329 deletions(-)
----------------------------------------------------------------------



[36/50] [abbrv] lucene-solr git commit: LUCENE-7075: clean up LegacyNumerics* usage in queries/ tests

Posted by no...@apache.org.
LUCENE-7075: clean up LegacyNumerics* usage in queries/ tests


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

Branch: refs/heads/apiv2
Commit: f9fbf8bc1d6fa7667d260ed48428ffefc8fc3c5d
Parents: 75f18ad
Author: Robert Muir <rm...@apache.org>
Authored: Tue Mar 8 11:17:12 2016 -0500
Committer: Robert Muir <rm...@apache.org>
Committed: Tue Mar 8 11:17:12 2016 -0500

----------------------------------------------------------------------
 .../lucene/queries/function/FunctionTestSetup.java  |  8 +++-----
 .../queries/function/TestFunctionQuerySort.java     |  4 ++--
 .../lucene/queries/function/TestValueSources.java   | 16 ----------------
 3 files changed, 5 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f9fbf8bc/lucene/queries/src/test/org/apache/lucene/queries/function/FunctionTestSetup.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/function/FunctionTestSetup.java b/lucene/queries/src/test/org/apache/lucene/queries/function/FunctionTestSetup.java
index d5a587d..2764a8f 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/function/FunctionTestSetup.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/function/FunctionTestSetup.java
@@ -21,12 +21,10 @@ import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.FieldType;
-import org.apache.lucene.document.LegacyFloatField;
-import org.apache.lucene.document.LegacyIntField;
 import org.apache.lucene.document.NumericDocValuesField;
 import org.apache.lucene.document.SortedDocValuesField;
+import org.apache.lucene.document.StoredField;
 import org.apache.lucene.document.TextField;
-import org.apache.lucene.document.Field.Store;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.queries.function.valuesource.FloatFieldSource;
@@ -143,11 +141,11 @@ public abstract class FunctionTestSetup extends LuceneTestCase {
     f = newField(TEXT_FIELD, "text of doc" + scoreAndID + textLine(i), customType2); // for regular search
     d.add(f);
 
-    f = new LegacyIntField(INT_FIELD, scoreAndID, Store.YES); // for function scoring
+    f = new StoredField(INT_FIELD, scoreAndID); // for function scoring
     d.add(f);
     d.add(new NumericDocValuesField(INT_FIELD, scoreAndID));
 
-    f = new LegacyFloatField(FLOAT_FIELD, scoreAndID, Store.YES); // for function scoring
+    f = new StoredField(FLOAT_FIELD, scoreAndID); // for function scoring
     d.add(f);
     d.add(new NumericDocValuesField(FLOAT_FIELD, Float.floatToRawIntBits(scoreAndID)));
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f9fbf8bc/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionQuerySort.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionQuerySort.java b/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionQuerySort.java
index b9e1eb2..67f67b2 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionQuerySort.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/function/TestFunctionQuerySort.java
@@ -20,8 +20,8 @@ import java.io.IOException;
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.LegacyIntField;
 import org.apache.lucene.document.NumericDocValuesField;
+import org.apache.lucene.document.StoredField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -102,7 +102,7 @@ public class TestFunctionQuerySort extends LuceneTestCase {
     RandomIndexWriter writer = new RandomIndexWriter(random(), dir, iwc);
 
     Document doc = new Document();
-    Field field = new LegacyIntField("value", 0, Field.Store.YES);
+    Field field = new StoredField("value", 0);
     Field dvField = new NumericDocValuesField("value", 0);
     doc.add(field);
     doc.add(dvField);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f9fbf8bc/lucene/queries/src/test/org/apache/lucene/queries/function/TestValueSources.java
----------------------------------------------------------------------
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/function/TestValueSources.java b/lucene/queries/src/test/org/apache/lucene/queries/function/TestValueSources.java
index 37a32da..509e0ab 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/function/TestValueSources.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/function/TestValueSources.java
@@ -24,11 +24,7 @@ import java.io.IOException;
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.LegacyDoubleField;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.LegacyFloatField;
-import org.apache.lucene.document.LegacyIntField;
-import org.apache.lucene.document.LegacyLongField;
 import org.apache.lucene.document.NumericDocValuesField;
 import org.apache.lucene.document.SortedDocValuesField;
 import org.apache.lucene.document.StringField;
@@ -120,20 +116,12 @@ public class TestValueSources extends LuceneTestCase {
     document.add(idField);
     Field idDVField = new SortedDocValuesField("id", new BytesRef());
     document.add(idDVField);
-    Field doubleField = new LegacyDoubleField("double", 0d, Field.Store.NO);
-    document.add(doubleField);
     Field doubleDVField = new NumericDocValuesField("double", 0);
     document.add(doubleDVField);
-    Field floatField = new LegacyFloatField("float", 0f, Field.Store.NO);
-    document.add(floatField);
     Field floatDVField = new NumericDocValuesField("float", 0);
     document.add(floatDVField);
-    Field intField = new LegacyIntField("int", 0, Field.Store.NO);
-    document.add(intField);
     Field intDVField = new NumericDocValuesField("int", 0);
     document.add(intDVField);
-    Field longField = new LegacyLongField("long", 0L, Field.Store.NO);
-    document.add(longField);
     Field longDVField = new NumericDocValuesField("long", 0);
     document.add(longDVField);
     Field stringField = new StringField("string", "", Field.Store.NO);
@@ -146,13 +134,9 @@ public class TestValueSources extends LuceneTestCase {
     for (String [] doc : documents) {
       idField.setStringValue(doc[0]);
       idDVField.setBytesValue(new BytesRef(doc[0]));
-      doubleField.setDoubleValue(Double.valueOf(doc[1]));
       doubleDVField.setLongValue(Double.doubleToRawLongBits(Double.valueOf(doc[1])));
-      floatField.setFloatValue(Float.valueOf(doc[2]));
       floatDVField.setLongValue(Float.floatToRawIntBits(Float.valueOf(doc[2])));
-      intField.setIntValue(Integer.valueOf(doc[3]));
       intDVField.setLongValue(Integer.valueOf(doc[3]));
-      longField.setLongValue(Long.valueOf(doc[4]));
       longDVField.setLongValue(Long.valueOf(doc[4]));
       stringField.setStringValue(doc[5]);
       stringDVField.setBytesValue(new BytesRef(doc[5]));


[06/50] [abbrv] lucene-solr git commit: LUCENE-7073: fix FieldType issues with Points

Posted by no...@apache.org.
LUCENE-7073: fix FieldType issues with Points


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

Branch: refs/heads/apiv2
Commit: 4df4cb07ac6bfe1a652bb784cb1a7f58e415701e
Parents: b87e392
Author: Robert Muir <rm...@apache.org>
Authored: Mon Mar 7 16:12:15 2016 -0500
Committer: Robert Muir <rm...@apache.org>
Committed: Mon Mar 7 16:13:05 2016 -0500

----------------------------------------------------------------------
 .../lucene/benchmark/byTask/feeds/DocMaker.java | 44 +++++++++-----------
 .../benchmark/byTask/tasks/ReadTokensTask.java  | 13 ++----
 .../lucene/codecs/lucene60/package-info.java    |  7 +++-
 .../org/apache/lucene/document/FieldType.java   | 24 +++++++----
 .../document/SortedNumericDocValuesField.java   |  4 +-
 .../apache/lucene/document/TestFieldType.java   | 15 +++++--
 .../apache/lucene/index/TestPointValues.java    |  3 +-
 .../apache/lucene/facet/range/DoubleRange.java  |  3 +-
 8 files changed, 59 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4df4cb07/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/DocMaker.java
----------------------------------------------------------------------
diff --git a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/DocMaker.java b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/DocMaker.java
index f2c863c..4afafc3 100644
--- a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/DocMaker.java
+++ b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/DocMaker.java
@@ -35,13 +35,12 @@ import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.lucene.benchmark.byTask.utils.Config;
 import org.apache.lucene.document.Document;
+import org.apache.lucene.document.DoublePoint;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.FieldType.LegacyNumericType;
+import org.apache.lucene.document.FloatPoint;
+import org.apache.lucene.document.IntPoint;
 import org.apache.lucene.document.FieldType;
-import org.apache.lucene.document.LegacyIntField;
-import org.apache.lucene.document.LegacyDoubleField;
-import org.apache.lucene.document.LegacyLongField;
-import org.apache.lucene.document.LegacyFloatField;
+import org.apache.lucene.document.LongPoint;
 import org.apache.lucene.document.StringField;
 import org.apache.lucene.document.TextField;
 
@@ -119,8 +118,8 @@ public class DocMaker implements Closeable {
         fields.put(ID_FIELD, new StringField(ID_FIELD, "", Field.Store.YES));
         fields.put(NAME_FIELD, new Field(NAME_FIELD, "", ft));
 
-        numericFields.put(DATE_MSEC_FIELD, new LegacyLongField(DATE_MSEC_FIELD, 0L, Field.Store.NO));
-        numericFields.put(TIME_SEC_FIELD, new LegacyIntField(TIME_SEC_FIELD, 0, Field.Store.NO));
+        numericFields.put(DATE_MSEC_FIELD, new LongPoint(DATE_MSEC_FIELD, 0L));
+        numericFields.put(TIME_SEC_FIELD, new IntPoint(TIME_SEC_FIELD, 0));
         
         doc = new Document();
       } else {
@@ -148,7 +147,7 @@ public class DocMaker implements Closeable {
       return f;
     }
 
-    Field getNumericField(String name, LegacyNumericType type) {
+    Field getNumericField(String name, Class<? extends Number> numericType) {
       Field f;
       if (reuseFields) {
         f = numericFields.get(name);
@@ -157,21 +156,16 @@ public class DocMaker implements Closeable {
       }
       
       if (f == null) {
-        switch(type) {
-        case INT:
-          f = new LegacyIntField(name, 0, Field.Store.NO);
-          break;
-        case LONG:
-          f = new LegacyLongField(name, 0L, Field.Store.NO);
-          break;
-        case FLOAT:
-          f = new LegacyFloatField(name, 0.0F, Field.Store.NO);
-          break;
-        case DOUBLE:
-          f = new LegacyDoubleField(name, 0.0, Field.Store.NO);
-          break;
-        default:
-          throw new AssertionError("Cannot get here");
+        if (numericType.equals(Integer.class)) {
+          f = new IntPoint(name, 0);
+        } else if (numericType.equals(Long.class)) {
+          f = new LongPoint(name, 0L);
+        } else if (numericType.equals(Float.class)) {
+          f = new FloatPoint(name, 0.0F);
+        } else if (numericType.equals(Double.class)) {
+          f = new DoublePoint(name, 0.0);
+        } else {
+          throw new UnsupportedOperationException("Unsupported numeric type: " + numericType);
         }
         if (reuseFields) {
           numericFields.put(name, f);
@@ -278,14 +272,14 @@ public class DocMaker implements Closeable {
       date = new Date();
     }
 
-    Field dateField = ds.getNumericField(DATE_MSEC_FIELD, FieldType.LegacyNumericType.LONG);
+    Field dateField = ds.getNumericField(DATE_MSEC_FIELD, Long.class);
     dateField.setLongValue(date.getTime());
     doc.add(dateField);
 
     util.cal.setTime(date);
     final int sec = util.cal.get(Calendar.HOUR_OF_DAY)*3600 + util.cal.get(Calendar.MINUTE)*60 + util.cal.get(Calendar.SECOND);
 
-    Field timeSecField = ds.getNumericField(TIME_SEC_FIELD, LegacyNumericType.INT);
+    Field timeSecField = ds.getNumericField(TIME_SEC_FIELD, Integer.class);
     timeSecField.setIntValue(sec);
     doc.add(timeSecField);
     

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4df4cb07/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTokensTask.java
----------------------------------------------------------------------
diff --git a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTokensTask.java b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTokensTask.java
index 4950d41..2e44b99 100644
--- a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTokensTask.java
+++ b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTokensTask.java
@@ -26,11 +26,7 @@ import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
 import org.apache.lucene.benchmark.byTask.PerfRunData;
 import org.apache.lucene.benchmark.byTask.feeds.DocMaker;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
-import org.apache.lucene.document.LegacyDoubleField;
-import org.apache.lucene.document.LegacyFloatField;
-import org.apache.lucene.document.LegacyIntField;
-import org.apache.lucene.document.LegacyLongField;
+import org.apache.lucene.index.IndexOptions;
 import org.apache.lucene.index.IndexableField;
 
 /**
@@ -73,11 +69,8 @@ public class ReadTokensTask extends PerfTask {
     Analyzer analyzer = getRunData().getAnalyzer();
     int tokenCount = 0;
     for(final IndexableField field : fields) {
-      if (!field.fieldType().tokenized() ||
-          field instanceof LegacyIntField ||
-          field instanceof LegacyLongField ||
-          field instanceof LegacyFloatField ||
-          field instanceof LegacyDoubleField) {
+      if (field.fieldType().indexOptions() == IndexOptions.NONE ||
+          field.fieldType().tokenized() == false) {
         continue;
       }
       

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4df4cb07/lucene/core/src/java/org/apache/lucene/codecs/lucene60/package-info.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene60/package-info.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene60/package-info.java
index 64531f5..03a17ba 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene60/package-info.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene60/package-info.java
@@ -194,9 +194,9 @@
  * </li>
  * <li>
  * {@link org.apache.lucene.codecs.lucene60.Lucene60PointsFormat Point values}.
- * Optional pair of files, recording dimesionally indexed fields, to enable fast
+ * Optional pair of files, recording dimensionally indexed fields, to enable fast
  * numeric range filtering and large numeric values like BigInteger and BigDecimal (1D)
- * and geo shape intersection (2D, 3D).
+ * and geographic shape intersection (2D, 3D).
  * </li>
  * </ul>
  * <p>Details on each of these are provided in their linked pages.</p>
@@ -396,6 +396,9 @@
  * contain the zlib-crc32 checksum of the file.</li>
  * <li>In version 4.9, DocValues has a new multi-valued numeric type (SortedNumeric)
  * that is suitable for faceting/sorting/analytics.
+ * <li>In version 5.4, DocValues have been improved to store more information on disk:
+ * addresses for binary fields and ord indexes for multi-valued fields.
+ * <li>In version 6.0, Points were added, for multi-dimensional range/distance search.
  * </li>
  * </ul>
  * <a name="Limitations"></a>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4df4cb07/lucene/core/src/java/org/apache/lucene/document/FieldType.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/FieldType.java b/lucene/core/src/java/org/apache/lucene/document/FieldType.java
index 1dfa879..ae84016 100644
--- a/lucene/core/src/java/org/apache/lucene/document/FieldType.java
+++ b/lucene/core/src/java/org/apache/lucene/document/FieldType.java
@@ -21,6 +21,7 @@ import org.apache.lucene.analysis.Analyzer; // javadocs
 import org.apache.lucene.index.DocValuesType;
 import org.apache.lucene.index.IndexOptions;
 import org.apache.lucene.index.IndexableFieldType;
+import org.apache.lucene.index.PointValues;
 import org.apache.lucene.util.LegacyNumericUtils;
 
 /**
@@ -75,8 +76,8 @@ public class FieldType implements IndexableFieldType  {
     this.numericType = ref.numericType();
     this.numericPrecisionStep = ref.numericPrecisionStep();
     this.docValuesType = ref.docValuesType();
-    this.dimensionCount = dimensionCount;
-    this.dimensionNumBytes = dimensionNumBytes;
+    this.dimensionCount = ref.dimensionCount;
+    this.dimensionNumBytes = ref.dimensionNumBytes;
     // Do not copy frozen!
   }
   
@@ -365,18 +366,24 @@ public class FieldType implements IndexableFieldType  {
    */
   public void setDimensions(int dimensionCount, int dimensionNumBytes) {
     if (dimensionCount < 0) {
-      throw new IllegalArgumentException("pointDimensionCount must be >= 0; got " + dimensionCount);
+      throw new IllegalArgumentException("dimensionCount must be >= 0; got " + dimensionCount);
+    }
+    if (dimensionCount > PointValues.MAX_DIMENSIONS) {
+      throw new IllegalArgumentException("dimensionCount must be <= " + PointValues.MAX_DIMENSIONS + "; got " + dimensionCount);
     }
     if (dimensionNumBytes < 0) {
-      throw new IllegalArgumentException("pointNumBytes must be >= 0; got " + dimensionNumBytes);
+      throw new IllegalArgumentException("dimensionNumBytes must be >= 0; got " + dimensionNumBytes);
+    }
+    if (dimensionCount > PointValues.MAX_NUM_BYTES) {
+      throw new IllegalArgumentException("dimensionNumBytes must be <= " + PointValues.MAX_NUM_BYTES + "; got " + dimensionNumBytes);
     }
     if (dimensionCount == 0) {
       if (dimensionNumBytes != 0) {
-        throw new IllegalArgumentException("when pointDimensionCount is 0 pointNumBytes must 0; got " + dimensionNumBytes);
+        throw new IllegalArgumentException("when dimensionCount is 0, dimensionNumBytes must 0; got " + dimensionNumBytes);
       }
     } else if (dimensionNumBytes == 0) {
       if (dimensionCount != 0) {
-        throw new IllegalArgumentException("when pointNumBytes is 0 pointDimensionCount must 0; got " + dimensionCount);
+        throw new IllegalArgumentException("when dimensionNumBytes is 0, dimensionCount must 0; got " + dimensionCount);
       }
     }
 
@@ -484,6 +491,8 @@ public class FieldType implements IndexableFieldType  {
   public int hashCode() {
     final int prime = 31;
     int result = 1;
+    result = prime * result + dimensionCount;
+    result = prime * result + dimensionNumBytes;
     result = prime * result + ((docValuesType == null) ? 0 : docValuesType.hashCode());
     result = prime * result + indexOptions.hashCode();
     result = prime * result + numericPrecisionStep;
@@ -504,6 +513,8 @@ public class FieldType implements IndexableFieldType  {
     if (obj == null) return false;
     if (getClass() != obj.getClass()) return false;
     FieldType other = (FieldType) obj;
+    if (dimensionCount != other.dimensionCount) return false;
+    if (dimensionNumBytes != other.dimensionNumBytes) return false;
     if (docValuesType != other.docValuesType) return false;
     if (indexOptions != other.indexOptions) return false;
     if (numericPrecisionStep != other.numericPrecisionStep) return false;
@@ -517,5 +528,4 @@ public class FieldType implements IndexableFieldType  {
     if (tokenized != other.tokenized) return false;
     return true;
   }
-
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4df4cb07/lucene/core/src/java/org/apache/lucene/document/SortedNumericDocValuesField.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/SortedNumericDocValuesField.java b/lucene/core/src/java/org/apache/lucene/document/SortedNumericDocValuesField.java
index 40ceb25..cbba218 100644
--- a/lucene/core/src/java/org/apache/lucene/document/SortedNumericDocValuesField.java
+++ b/lucene/core/src/java/org/apache/lucene/document/SortedNumericDocValuesField.java
@@ -31,10 +31,10 @@ import org.apache.lucene.index.DocValuesType;
  * 
  * <p>
  * Note that if you want to encode doubles or floats with proper sort order,
- * you will need to encode them with {@link org.apache.lucene.util.LegacyNumericUtils}:
+ * you will need to encode them with {@link org.apache.lucene.util.NumericUtils}:
  * 
  * <pre class="prettyprint">
- *   document.add(new SortedNumericDocValuesField(name, LegacyNumericUtils.floatToSortableInt(-5.3f)));
+ *   document.add(new SortedNumericDocValuesField(name, NumericUtils.floatToSortableInt(-5.3f)));
  * </pre>
  * 
  * <p>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4df4cb07/lucene/core/src/test/org/apache/lucene/document/TestFieldType.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/document/TestFieldType.java b/lucene/core/src/test/org/apache/lucene/document/TestFieldType.java
index 65f32d8..c49d4e0 100644
--- a/lucene/core/src/test/org/apache/lucene/document/TestFieldType.java
+++ b/lucene/core/src/test/org/apache/lucene/document/TestFieldType.java
@@ -23,6 +23,7 @@ import java.lang.reflect.Modifier;
 import org.apache.lucene.document.FieldType.LegacyNumericType;
 import org.apache.lucene.index.DocValuesType;
 import org.apache.lucene.index.IndexOptions;
+import org.apache.lucene.index.PointValues;
 import org.apache.lucene.util.LuceneTestCase;
 
 import com.carrotsearch.randomizedtesting.generators.RandomPicks;
@@ -70,6 +71,10 @@ public class TestFieldType extends LuceneTestCase {
     FieldType ft10 = new FieldType();
     ft10.setStoreTermVectors(true);
     assertFalse(ft10.equals(ft));
+    
+    FieldType ft11 = new FieldType();
+    ft11.setDimensions(1, 4);
+    assertFalse(ft11.equals(ft));
   }
 
   public void testPointsToString() {
@@ -90,14 +95,16 @@ public class TestFieldType extends LuceneTestCase {
   }
 
   private static FieldType randomFieldType() throws Exception {
+    // setDimensions handled special as values must be in-bounds.
+    Method setDimensionsMethod = FieldType.class.getMethod("setDimensions", int.class, int.class);
     FieldType ft = new FieldType();
     for (Method method : FieldType.class.getMethods()) {
-      if ((method.getModifiers() & Modifier.PUBLIC) != 0 && method.getName().startsWith("set")) {
+      if (method.getName().startsWith("set")) {
         final Class<?>[] parameterTypes = method.getParameterTypes();
         final Object[] args = new Object[parameterTypes.length];
-        if (method.getName().equals("setPointDimensions")) {
-          args[0] = 1 + random().nextInt(15);
-          args[1] = 1 + random().nextInt(100);
+        if (method.equals(setDimensionsMethod)) {
+          args[0] = 1 + random().nextInt(PointValues.MAX_DIMENSIONS);
+          args[1] = 1 + random().nextInt(PointValues.MAX_NUM_BYTES);
         } else {
           for (int i = 0; i < args.length; ++i) {
             args[i] = randomValue(parameterTypes[i]);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4df4cb07/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java b/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
index 9faa0bc..7231b1a 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestPointValues.java
@@ -385,9 +385,8 @@ public class TestPointValues extends LuceneTestCase {
     for(int i=0;i<values.length;i++) {
       values[i] = new byte[4];
     }
-    doc.add(new BinaryPoint("dim", values));
     expectThrows(IllegalArgumentException.class, () -> {
-      w.addDocument(doc);
+      doc.add(new BinaryPoint("dim", values));
     });
 
     Document doc2 = new Document();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4df4cb07/lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRange.java
----------------------------------------------------------------------
diff --git a/lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRange.java b/lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRange.java
index 7585708..6f005ed 100644
--- a/lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRange.java
+++ b/lucene/facet/src/java/org/apache/lucene/facet/range/DoubleRange.java
@@ -32,7 +32,6 @@ import org.apache.lucene.search.Query;
 import org.apache.lucene.search.Scorer;
 import org.apache.lucene.search.TwoPhaseIterator;
 import org.apache.lucene.search.Weight;
-import org.apache.lucene.util.LegacyNumericUtils;
 import org.apache.lucene.util.NumericUtils;
 
 /** Represents a range over double values.
@@ -50,7 +49,7 @@ public final class DoubleRange extends Range {
     super(label);
 
     // TODO: if DoubleDocValuesField used
-    // LegacyNumericUtils.doubleToSortableLong format (instead of
+    // NumericUtils.doubleToSortableLong format (instead of
     // Double.doubleToRawLongBits) we could do comparisons
     // in long space 
 


[13/50] [abbrv] lucene-solr git commit: LUCENE-7056: Geo3D package re-org

Posted by no...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideSouthRectangle.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideSouthRectangle.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideSouthRectangle.java
new file mode 100644
index 0000000..da9799a
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWideSouthRectangle.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Bounding box wider than PI but limited on three sides (top lat,
+ * left lon, right lon).
+ *
+ * @lucene.internal
+ */
+public class GeoWideSouthRectangle extends GeoBaseBBox {
+  /** Top latitude of rect */
+  protected final double topLat;
+  /** Left longitude of rect */
+  protected final double leftLon;
+  /** Right longitude of rect */
+  protected final double rightLon;
+
+  /** Cosine of middle latitude */
+  protected final double cosMiddleLat;
+
+  /** Upper left hand corner */
+  protected final GeoPoint ULHC;
+  /** Upper right hand corner */
+  protected final GeoPoint URHC;
+
+  /** The top plane */
+  protected final SidedPlane topPlane;
+  /** The left plane */
+  protected final SidedPlane leftPlane;
+  /** The right plane */
+  protected final SidedPlane rightPlane;
+
+  /** Notable points for top plane */
+  protected final GeoPoint[] topPlanePoints;
+  /** Notable points for left plane */
+  protected final GeoPoint[] leftPlanePoints;
+  /** Notable points for right plane */
+  protected final GeoPoint[] rightPlanePoints;
+
+  /** Center point */
+  protected final GeoPoint centerPoint;
+
+  /** Left/right bounds */
+  protected final EitherBound eitherBound;
+
+  /** A point on the edge */
+  protected final GeoPoint[] edgePoints;
+
+  /**
+   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}.
+   * Horizontal angle must be greater than or equal to PI.
+   */
+  public GeoWideSouthRectangle(final PlanetModel planetModel, final double topLat, final double leftLon, double rightLon) {
+    super(planetModel);
+    // Argument checking
+    if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
+      throw new IllegalArgumentException("Top latitude out of range");
+    if (leftLon < -Math.PI || leftLon > Math.PI)
+      throw new IllegalArgumentException("Left longitude out of range");
+    if (rightLon < -Math.PI || rightLon > Math.PI)
+      throw new IllegalArgumentException("Right longitude out of range");
+    double extent = rightLon - leftLon;
+    if (extent < 0.0) {
+      extent += 2.0 * Math.PI;
+    }
+    if (extent < Math.PI)
+      throw new IllegalArgumentException("Width of rectangle too small");
+
+    this.topLat = topLat;
+    this.leftLon = leftLon;
+    this.rightLon = rightLon;
+
+    final double sinTopLat = Math.sin(topLat);
+    final double cosTopLat = Math.cos(topLat);
+    final double sinLeftLon = Math.sin(leftLon);
+    final double cosLeftLon = Math.cos(leftLon);
+    final double sinRightLon = Math.sin(rightLon);
+    final double cosRightLon = Math.cos(rightLon);
+
+    // Now build the four points
+    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);
+    this.cosMiddleLat = Math.cos(middleLat);
+    // Normalize
+    while (leftLon > rightLon) {
+      rightLon += Math.PI * 2.0;
+    }
+    final double middleLon = (leftLon + rightLon) * 0.5;
+    final double sinMiddleLon = Math.sin(middleLon);
+    final double cosMiddleLon = Math.cos(middleLon);
+
+    this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
+
+    this.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
+    this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
+    this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
+
+    this.topPlanePoints = new GeoPoint[]{ULHC, URHC};
+    this.leftPlanePoints = new GeoPoint[]{ULHC, planetModel.SOUTH_POLE};
+    this.rightPlanePoints = new GeoPoint[]{URHC, planetModel.SOUTH_POLE};
+
+    this.eitherBound = new EitherBound();
+    
+    this.edgePoints = new GeoPoint[]{planetModel.SOUTH_POLE};
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    final double newTopLat = topLat + angle;
+    final double newBottomLat = -Math.PI * 0.5;
+    // Figuring out when we escalate to a special case requires some prefiguring
+    double currentLonSpan = rightLon - leftLon;
+    if (currentLonSpan < 0.0)
+      currentLonSpan += Math.PI * 2.0;
+    double newLeftLon = leftLon - angle;
+    double newRightLon = rightLon + angle;
+    if (currentLonSpan + 2.0 * angle >= Math.PI * 2.0) {
+      newLeftLon = -Math.PI;
+      newRightLon = Math.PI;
+    }
+    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return topPlane.isWithin(x, y, z) &&
+        (leftPlane.isWithin(x, y, z) ||
+            rightPlane.isWithin(x, y, z));
+  }
+
+  @Override
+  public double getRadius() {
+    // Here we compute the distance from the middle point to one of the corners.  However, we need to be careful
+    // to use the longest of three distances: the distance to a corner on the top; the distnace to a corner on the bottom, and
+    // the distance to the right or left edge from the center.
+    final double centerAngle = (rightLon - (rightLon + leftLon) * 0.5) * cosMiddleLat;
+    final double topAngle = centerPoint.arcDistance(URHC);
+    return Math.max(centerAngle, topAngle);
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    return centerPoint;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    // Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
+    // requires crossing into the right part of the other.  So intersection can ignore the left/right bounds.
+    return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, eitherBound) ||
+        p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, topPlane) ||
+        p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, topPlane);
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    bounds.isWide()
+      .addHorizontalPlane(planetModel, topLat, topPlane, eitherBound)
+      .addVerticalPlane(planetModel, rightLon, rightPlane, topPlane)
+      .addVerticalPlane(planetModel, leftLon, leftPlane, topPlane)
+      .addPoint(ULHC).addPoint(URHC).addPoint(planetModel.SOUTH_POLE);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    //System.err.println(this+" comparing to "+path);
+    final int insideRectangle = isShapeInsideBBox(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some inside");
+      return OVERLAPS;
+    }
+
+    final boolean insideShape = path.isWithin(planetModel.SOUTH_POLE);
+
+    if (insideRectangle == ALL_INSIDE && insideShape) {
+      //System.err.println(" both inside each other");
+      return OVERLAPS;
+    }
+
+    if (path.intersects(topPlane, topPlanePoints, eitherBound) ||
+        path.intersects(leftPlane, leftPlanePoints, topPlane) ||
+        path.intersects(rightPlane, rightPlanePoints, topPlane)) {
+      //System.err.println(" edges intersect");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      //System.err.println(" shape inside rectangle");
+      return WITHIN;
+    }
+
+    if (insideShape) {
+      //System.err.println(" rectangle inside shape");
+      return CONTAINS;
+    }
+
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @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, eitherBound);
+    // Because the rectangle exceeds 180 degrees, it is safe to compute the horizontally 
+    // unbounded distance to both the left and the right and only take the minimum of the two.
+    final double leftDistance = distanceStyle.computeDistance(planetModel, leftPlane, x,y,z, topPlane);
+    final double rightDistance = distanceStyle.computeDistance(planetModel, rightPlane, x,y,z, topPlane);
+    
+    final double ULHCDistance = distanceStyle.computeDistance(ULHC, x,y,z);
+    final double URHCDistance = distanceStyle.computeDistance(URHC, x,y,z);
+    
+    return Math.min(
+      Math.min(
+        topDistance,
+        Math.min(leftDistance, rightDistance)),
+      Math.min(ULHCDistance, URHCDistance));
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof GeoWideSouthRectangle))
+      return false;
+    GeoWideSouthRectangle other = (GeoWideSouthRectangle) o;
+    return super.equals(o) && other.ULHC.equals(ULHC) && other.URHC.equals(URHC);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + ULHC.hashCode();
+    result = 31 * result + URHC.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "GeoWideSouthRectangle: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
+  }
+
+  /** Membership implementation representing width more than 180.
+   */
+  protected class EitherBound implements Membership {
+    /** Constructor.
+     */
+    public EitherBound() {
+    }
+
+    @Override
+    public boolean isWithin(final Vector v) {
+      return leftPlane.isWithin(v) || rightPlane.isWithin(v);
+    }
+
+    @Override
+    public boolean isWithin(final double x, final double y, final double z) {
+      return leftPlane.isWithin(x, y, z) || rightPlane.isWithin(x, y, z);
+    }
+  }
+}
+  
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWorld.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWorld.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWorld.java
new file mode 100755
index 0000000..25bdc96
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoWorld.java
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Bounding box including the entire world.
+ *
+ * @lucene.internal
+ */
+public class GeoWorld extends GeoBaseBBox {
+  /** No points on the edge of the shape */
+  protected final static GeoPoint[] edgePoints = new GeoPoint[0];
+  /** Point in the middle of the world */
+  protected final GeoPoint originPoint;
+  
+  /** Constructor.
+   *@param planetModel is the planet model.
+   */
+  public GeoWorld(final PlanetModel planetModel) {
+    super(planetModel);
+    originPoint = new GeoPoint(planetModel.ab, 1.0, 0.0, 0.0);
+  }
+
+  @Override
+  public GeoBBox expand(final double angle) {
+    return this;
+  }
+
+  @Override
+  public double getRadius() {
+    return Math.PI;
+  }
+
+  @Override
+  public GeoPoint getCenter() {
+    // Totally arbitrary
+    return originPoint;
+  }
+
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return true;
+  }
+
+  @Override
+  public GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+
+  @Override
+  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
+    return false;
+  }
+
+  @Override
+  public void getBounds(Bounds bounds) {
+    super.getBounds(bounds);
+    // Unnecessary
+    //bounds.noLongitudeBound().noTopLatitudeBound().noBottomLatitudeBound();
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    if (path.getEdgePoints().length > 0)
+      // Path is always within the world
+      return WITHIN;
+
+    return OVERLAPS;
+  }
+
+  @Override
+  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
+    return 0.0;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof GeoWorld))
+      return false;
+    return super.equals(o);
+  }
+
+  @Override
+  public int hashCode() {
+    return super.hashCode();
+  }
+
+  @Override
+  public String toString() {
+    return "GeoWorld: {planetmodel="+planetModel+"}";
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LatLonBounds.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LatLonBounds.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LatLonBounds.java
new file mode 100644
index 0000000..627fdae
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LatLonBounds.java
@@ -0,0 +1,322 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * 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() {
+    return noLongitudeBound();
+  }
+
+  @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() {
+    noLongitudeBound = true;
+    leftLongitude = null;
+    rightLongitude = null;
+    return this;
+  }
+
+  @Override
+  public Bounds noTopLatitudeBound() {
+    noTopLatitudeBound = true;
+    maxLatitude = null;
+    return this;
+  }
+
+  @Override
+  public Bounds noBottomLatitudeBound() {
+    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 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;
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearDistance.java
new file mode 100644
index 0000000..0c89a16
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearDistance.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Linear distance computation style.
+ *
+ * @lucene.experimental
+ */
+public class LinearDistance implements DistanceStyle {
+  
+  /** A convenient instance */
+  public final static LinearDistance INSTANCE = new LinearDistance();
+  
+  /** Constructor.
+   */
+  public LinearDistance() {
+  }
+  
+  @Override
+  public double computeDistance(final GeoPoint point1, final GeoPoint point2) {
+    return point1.linearDistance(point2);
+  }
+  
+  @Override
+  public double computeDistance(final GeoPoint point1, final double x2, final double y2, final double z2) {
+    return point1.linearDistance(x2,y2,z2);
+  }
+
+  @Override
+  public double computeDistance(final PlanetModel planetModel, final Plane plane, final GeoPoint point, final Membership... bounds) {
+    return plane.linearDistance(planetModel, point, bounds);
+  }
+  
+  @Override
+  public double computeDistance(final PlanetModel planetModel, final Plane plane, final double x, final double y, final double z, final Membership... bounds) {
+    return plane.linearDistance(planetModel, x,y,z, bounds);
+  }
+
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearSquaredDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearSquaredDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearSquaredDistance.java
new file mode 100644
index 0000000..3fc37da
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/LinearSquaredDistance.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Linear squared distance computation style.
+ *
+ * @lucene.experimental
+ */
+public class LinearSquaredDistance implements DistanceStyle {
+  
+  /** A convenient instance */
+  public final static LinearSquaredDistance INSTANCE = new LinearSquaredDistance();
+  
+  /** Constructor.
+   */
+  public LinearSquaredDistance() {
+  }
+  
+  @Override
+  public double computeDistance(final GeoPoint point1, final GeoPoint point2) {
+    return point1.linearDistanceSquared(point2);
+  }
+  
+  @Override
+  public double computeDistance(final GeoPoint point1, final double x2, final double y2, final double z2) {
+    return point1.linearDistanceSquared(x2,y2,z2);
+  }
+
+  @Override
+  public double computeDistance(final PlanetModel planetModel, final Plane plane, final GeoPoint point, final Membership... bounds) {
+    return plane.linearDistanceSquared(planetModel, point, bounds);
+  }
+  
+  @Override
+  public double computeDistance(final PlanetModel planetModel, final Plane plane, final double x, final double y, final double z, final Membership... bounds) {
+    return plane.linearDistanceSquared(planetModel, x,y,z, bounds);
+  }
+
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Membership.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Membership.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Membership.java
new file mode 100755
index 0000000..0cf6ff0
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/Membership.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Implemented by Geo3D shapes that can calculate if a point is within it or not.
+ *
+ * @lucene.experimental
+ */
+public interface Membership {
+
+  /**
+   * Check if a point is within this shape.
+   *
+   * @param point is the point to check.
+   * @return true if the point is within this shape
+   */
+  public default 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
+   */
+  public boolean isWithin(final double x, final double y, final double z);
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalDistance.java
new file mode 100644
index 0000000..50b2c7f
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalDistance.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Normal distance computation style.
+ *
+ * @lucene.experimental
+ */
+public class NormalDistance implements DistanceStyle {
+  
+  /** A convenient instance */
+  public final static NormalDistance INSTANCE = new NormalDistance();
+  
+  /** Constructor.
+   */
+  public NormalDistance() {
+  }
+  
+  @Override
+  public double computeDistance(final GeoPoint point1, final GeoPoint point2) {
+    return point1.normalDistance(point2);
+  }
+  
+  @Override
+  public double computeDistance(final GeoPoint point1, final double x2, final double y2, final double z2) {
+    return point1.normalDistance(x2,y2,z2);
+  }
+
+  @Override
+  public double computeDistance(final PlanetModel planetModel, final Plane plane, final GeoPoint point, final Membership... bounds) {
+    return plane.normalDistance(point, bounds);
+  }
+  
+  @Override
+  public double computeDistance(final PlanetModel planetModel, final Plane plane, final double x, final double y, final double z, final Membership... bounds) {
+    return plane.normalDistance(x,y,z, bounds);
+  }
+
+}
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f7f81c32/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalSquaredDistance.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalSquaredDistance.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalSquaredDistance.java
new file mode 100644
index 0000000..a355d09
--- /dev/null
+++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/NormalSquaredDistance.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+package org.apache.lucene.spatial3d.geom;
+
+/**
+ * Normal squared distance computation style.
+ *
+ * @lucene.experimental
+ */
+public class NormalSquaredDistance implements DistanceStyle {
+  
+  /** A convenient instance */
+  public final static NormalSquaredDistance INSTANCE = new NormalSquaredDistance();
+  
+  /** Constructor.
+   */
+  public NormalSquaredDistance() {
+  }
+  
+  @Override
+  public double computeDistance(final GeoPoint point1, final GeoPoint point2) {
+    return point1.normalDistanceSquared(point2);
+  }
+  
+  @Override
+  public double computeDistance(final GeoPoint point1, final double x2, final double y2, final double z2) {
+    return point1.normalDistanceSquared(x2,y2,z2);
+  }
+
+  @Override
+  public double computeDistance(final PlanetModel planetModel, final Plane plane, final GeoPoint point, final Membership... bounds) {
+    return plane.normalDistanceSquared(point, bounds);
+  }
+  
+  @Override
+  public double computeDistance(final PlanetModel planetModel, final Plane plane, final double x, final double y, final double z, final Membership... bounds) {
+    return plane.normalDistanceSquared(x,y,z, bounds);
+  }
+
+}
+
+