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

svn commit: r1675374 [2/2] - in /lucene/dev/branches/lucene6196/lucene/spatial/src: java/org/apache/lucene/spatial/spatial4j/geo3d/ test/org/apache/lucene/spatial/spatial4j/

Added: lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoSouthRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoSouthRectangle.java?rev=1675374&view=auto
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoSouthRectangle.java (added)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoSouthRectangle.java Wed Apr 22 14:47:00 2015
@@ -0,0 +1,238 @@
+package org.apache.lucene.spatial.spatial4j.geo3d;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** 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
+* GeoWideSouthRectangle.
+*/
+public class GeoSouthRectangle extends GeoBBoxBase
+{
+    public final double topLat;
+    public final double leftLon;
+    public final double rightLon;
+      
+    public final double cosMiddleLat;
+      
+    public final GeoPoint ULHC;
+    public final GeoPoint URHC;
+    
+    public final SidedPlane topPlane;
+    public final SidedPlane leftPlane;
+    public final SidedPlane rightPlane;
+    
+    public final GeoPoint[] topPlanePoints;
+    public final GeoPoint[] leftPlanePoints;
+    public final GeoPoint[] rightPlanePoints;
+    
+    public final GeoPoint centerPoint;
+
+    public final GeoPoint[] edgePoints = new GeoPoint[]{SOUTH_POLE};
+    
+    /** Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI} */
+    public GeoSouthRectangle(final double topLat, final double leftLon, double rightLon)
+    {
+        // 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(sinTopLat,sinLeftLon,cosTopLat,cosLeftLon);
+        this.URHC = new GeoPoint(sinTopLat,sinRightLon,cosTopLat,cosRightLon);
+        
+        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(sinMiddleLat,sinMiddleLon,cosMiddleLat,cosMiddleLon);
+
+        this.topPlane = new SidedPlane(centerPoint,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,SOUTH_POLE};
+        this.rightPlanePoints = new GeoPoint[]{URHC,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(newTopLat,newBottomLat,newLeftLon,newRightLon);
+    }
+
+    @Override
+    public boolean isWithin(final Vector point)
+    {
+        return topPlane.isWithin(point) &&
+          leftPlane.isWithin(point) &&
+          rightPlane.isWithin(point);
+    }
+
+    @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 boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds)
+    {
+        return p.intersects(topPlane,notablePoints,topPlanePoints,bounds,leftPlane,rightPlane) ||
+          p.intersects(leftPlane,notablePoints,leftPlanePoints,bounds,rightPlane,topPlane) ||
+          p.intersects(rightPlane,notablePoints,rightPlanePoints,bounds,leftPlane,topPlane);
+    }
+
+    /** Compute longitude/latitude bounds for the shape.
+    *@param bounds is the optional input bounds object.  If this is null,
+    * a bounds object will be created.  Otherwise, the input object will be modified.
+    *@return a Bounds object describing the shape's bounds.  If the bounds cannot
+    * be computed, then return a Bounds object with noLongitudeBound,
+    * noTopLatitudeBound, and noBottomLatitudeBound.
+    */
+    @Override
+    public Bounds getBounds(Bounds bounds)
+    {
+        if (bounds == null)
+            bounds = new Bounds();
+        bounds.addLatitudeZone(topLat).noBottomLatitudeBound()
+            .addLongitudeSlice(leftLon,rightLon);
+        return bounds;
+    }
+
+    @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(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
+    public boolean equals(Object o)
+    {
+        if (!(o instanceof GeoSouthRectangle))
+            return false;
+        GeoSouthRectangle other = (GeoSouthRectangle)o;
+        return other.ULHC.equals(ULHC) && other.URHC.equals(URHC);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = ULHC.hashCode();
+        result = 31 * result + URHC.hashCode();
+        return result;
+    }
+    
+    @Override
+    public String toString() {
+        return "GeoSouthRectangle: {toplat="+topLat+"("+topLat*180.0/Math.PI+"), leftlon="+leftLon+"("+leftLon*180.0/Math.PI+"), rightlon="+rightLon+"("+rightLon*180.0/Math.PI+")}";
+    }
+}
+  
+

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideDegenerateHorizontalLine.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideDegenerateHorizontalLine.java?rev=1675374&r1=1675373&r2=1675374&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideDegenerateHorizontalLine.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideDegenerateHorizontalLine.java Wed Apr 22 14:47:00 2015
@@ -31,7 +31,9 @@ public class GeoWideDegenerateHorizontal
     public final Plane plane;
     public final SidedPlane leftPlane;
     public final SidedPlane rightPlane;
-      
+
+    public final GeoPoint[] planePoints;
+    
     public final GeoPoint centerPoint;
 
     public final EitherBound eitherBound;
@@ -87,6 +89,8 @@ public class GeoWideDegenerateHorizontal
         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};
@@ -115,7 +119,7 @@ public class GeoWideDegenerateHorizontal
     {
         if (point == null)
             return false;
-        return plane.evaluate(point) == 0.0 &&
+        return plane.evaluateIsZero(point) &&
           (leftPlane.isWithin(point) ||
           rightPlane.isWithin(point));
     }
@@ -123,7 +127,7 @@ public class GeoWideDegenerateHorizontal
     @Override
     public boolean isWithin(final double x, final double y, final double z)
     {
-        return plane.evaluate(x,y,z) == 0.0 &&
+        return plane.evaluateIsZero(x,y,z) &&
           (leftPlane.isWithin(x,y,z) ||
           rightPlane.isWithin(x,y,z));
     }
@@ -146,11 +150,11 @@ public class GeoWideDegenerateHorizontal
     }
       
     @Override
-    public boolean intersects(final Plane p, final Membership... bounds)
+    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(plane,bounds,eitherBound);
+        return p.intersects(plane,notablePoints,planePoints,bounds,eitherBound);
     }
 
     /** Compute longitude/latitude bounds for the shape.
@@ -172,7 +176,7 @@ public class GeoWideDegenerateHorizontal
 
     @Override
     public int getRelationship(final GeoShape path) {
-        if (path.intersects(plane,eitherBound)) {
+        if (path.intersects(plane,planePoints,eitherBound)) {
             return OVERLAPS;
         }
 

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideLongitudeSlice.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideLongitudeSlice.java?rev=1675374&r1=1675373&r2=1675374&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideLongitudeSlice.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideLongitudeSlice.java Wed Apr 22 14:47:00 2015
@@ -27,10 +27,12 @@ public class GeoWideLongitudeSlice exten
       
     public final SidedPlane leftPlane;
     public final SidedPlane rightPlane;
-      
+    
+    public final static GeoPoint[] planePoints = new GeoPoint[]{NORTH_POLE,SOUTH_POLE};
+    
     public final GeoPoint centerPoint;
-    public final GeoPoint northPole = new GeoPoint(0.0,0.0,1.0);
-    public final GeoPoint[] edgePoints = new GeoPoint[]{northPole};
+
+    public final static GeoPoint[] edgePoints = new GeoPoint[]{NORTH_POLE};
     
     /** Accepts only values in the following ranges: lon: {@code -PI -> PI}.
     * Horizantal angle must be greater than or equal to PI.
@@ -115,12 +117,12 @@ public class GeoWideLongitudeSlice exten
     }
       
     @Override
-    public boolean intersects(final Plane p, final Membership... bounds)
+    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(leftPlane,bounds) ||
-          p.intersects(rightPlane,bounds);
+        return  p.intersects(leftPlane,notablePoints,planePoints,bounds) ||
+          p.intersects(rightPlane,notablePoints,planePoints,bounds);
     }
 
     /** Compute longitude/latitude bounds for the shape.
@@ -146,13 +148,13 @@ public class GeoWideLongitudeSlice exten
         if (insideRectangle == SOME_INSIDE)
             return OVERLAPS;
 
-        final boolean insideShape = path.isWithin(northPole);
+        final boolean insideShape = path.isWithin(NORTH_POLE);
         
         if (insideRectangle == ALL_INSIDE && insideShape)
             return OVERLAPS;
 
-        if (path.intersects(leftPlane) ||
-            path.intersects(rightPlane))
+        if (path.intersects(leftPlane,planePoints) ||
+            path.intersects(rightPlane,planePoints))
             return OVERLAPS;
 
         if (insideRectangle == ALL_INSIDE)

Added: lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideNorthRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideNorthRectangle.java?rev=1675374&view=auto
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideNorthRectangle.java (added)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideNorthRectangle.java Wed Apr 22 14:47:00 2015
@@ -0,0 +1,263 @@
+package org.apache.lucene.spatial.spatial4j.geo3d;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Bounding box wider than PI but limited on three sides (
+* bottom lat, left lon, right lon).
+*/
+public class GeoWideNorthRectangle extends GeoBBoxBase
+{
+    public final double bottomLat;
+    public final double leftLon;
+    public final double rightLon;
+      
+    public final double cosMiddleLat;
+      
+    public final GeoPoint LRHC;
+    public final GeoPoint LLHC;
+    
+    public final SidedPlane bottomPlane;
+    public final SidedPlane leftPlane;
+    public final SidedPlane rightPlane;
+
+    public final GeoPoint[] bottomPlanePoints;
+    public final GeoPoint[] leftPlanePoints;
+    public final GeoPoint[] rightPlanePoints;
+
+    public final GeoPoint centerPoint;
+
+    public final EitherBound eitherBound;
+    
+    public final GeoPoint[] edgePoints = new GeoPoint[]{NORTH_POLE};
+    
+    /** 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 double bottomLat, final double leftLon, double rightLon)
+    {
+        // 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(sinBottomLat,sinRightLon,cosBottomLat,cosRightLon);
+        this.LLHC = new GeoPoint(sinBottomLat,sinLeftLon,cosBottomLat,cosLeftLon);
+        
+        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(sinMiddleLat,sinMiddleLon,cosMiddleLat,cosMiddleLon);
+
+        this.bottomPlane = new SidedPlane(centerPoint,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[]{NORTH_POLE,LLHC};
+        this.rightPlanePoints = new GeoPoint[]{NORTH_POLE,LRHC};
+
+        this.eitherBound = new EitherBound();
+    }
+
+    @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(newTopLat,newBottomLat,newLeftLon,newRightLon);
+    }
+
+    @Override
+    public boolean isWithin(final Vector point)
+    {
+        return
+          bottomPlane.isWithin(point) &&
+          (leftPlane.isWithin(point) ||
+          rightPlane.isWithin(point));
+    }
+
+    @Override
+    public boolean isWithin(final double x, final double y, final double z)
+    {
+        return
+          bottomPlane.isWithin(x,y,z) &&
+          (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;
+    }
+      
+    @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(bottomPlane,notablePoints,bottomPlanePoints,bounds,eitherBound) ||
+          p.intersects(leftPlane,notablePoints,leftPlanePoints,bounds,bottomPlane) ||
+          p.intersects(rightPlane,notablePoints,rightPlanePoints,bounds,bottomPlane);
+    }
+
+    /** Compute longitude/latitude bounds for the shape.
+    *@param bounds is the optional input bounds object.  If this is null,
+    * a bounds object will be created.  Otherwise, the input object will be modified.
+    *@return a Bounds object describing the shape's bounds.  If the bounds cannot
+    * be computed, then return a Bounds object with noLongitudeBound,
+    * noTopLatitudeBound, and noBottomLatitudeBound.
+    */
+    @Override
+    public Bounds getBounds(Bounds bounds)
+    {
+        if (bounds == null)
+            bounds = new Bounds();
+        bounds.noTopLatitudeBound().addLatitudeZone(bottomLat)
+            .addLongitudeSlice(leftLon,rightLon);
+        return bounds;
+    }
+
+    @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(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
+    public boolean equals(Object o)
+    {
+        if (!(o instanceof GeoWideNorthRectangle))
+            return false;
+        GeoWideNorthRectangle other = (GeoWideNorthRectangle)o;
+        return other.LLHC.equals(LLHC) && other.LRHC.equals(LRHC);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = LLHC.hashCode();
+        result = 31 * result + LRHC.hashCode();
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "GeoWideNorthRectangle: {bottomlat="+bottomLat+"("+bottomLat*180.0/Math.PI+"), leftlon="+leftLon+"("+leftLon*180.0/Math.PI+"), rightlon="+rightLon+"("+rightLon*180.0/Math.PI+")}";
+    }
+
+    protected class EitherBound implements Membership {
+        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);
+        }
+    }
+}
+  
+

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideRectangle.java?rev=1675374&r1=1675373&r2=1675374&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideRectangle.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideRectangle.java Wed Apr 22 14:47:00 2015
@@ -38,7 +38,12 @@ public class GeoWideRectangle extends Ge
     public final SidedPlane bottomPlane;
     public final SidedPlane leftPlane;
     public final SidedPlane rightPlane;
-      
+
+    public final GeoPoint[] topPlanePoints;
+    public final GeoPoint[] bottomPlanePoints;
+    public final GeoPoint[] leftPlanePoints;
+    public final GeoPoint[] rightPlanePoints;
+
     public final GeoPoint centerPoint;
 
     public final EitherBound eitherBound;
@@ -105,7 +110,12 @@ public class GeoWideRectangle extends Ge
         this.bottomPlane = new SidedPlane(centerPoint,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};
@@ -166,14 +176,14 @@ public class GeoWideRectangle extends Ge
     }
       
     @Override
-    public boolean intersects(final Plane p, final Membership... bounds)
+    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(topPlane,bounds,bottomPlane,eitherBound) ||
-          p.intersects(bottomPlane,bounds,topPlane,eitherBound) ||
-          p.intersects(leftPlane,bounds,topPlane,bottomPlane) ||
-          p.intersects(rightPlane,bounds,topPlane,bottomPlane);
+        return p.intersects(topPlane,notablePoints,topPlanePoints,bounds,bottomPlane,eitherBound) ||
+          p.intersects(bottomPlane,notablePoints,bottomPlanePoints,bounds,topPlane,eitherBound) ||
+          p.intersects(leftPlane,notablePoints,leftPlanePoints,bounds,topPlane,bottomPlane) ||
+          p.intersects(rightPlane,notablePoints,rightPlanePoints,bounds,topPlane,bottomPlane);
     }
 
     /** Compute longitude/latitude bounds for the shape.
@@ -195,30 +205,40 @@ public class GeoWideRectangle extends Ge
 
     @Override
     public int getRelationship(final GeoShape path) {
+        //System.err.println(this+" comparing to "+path);
         final int insideRectangle = isShapeInsideBBox(path);
-        if (insideRectangle == SOME_INSIDE)
+        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,bottomPlane,eitherBound) ||
-            path.intersects(bottomPlane,topPlane,eitherBound) ||
-            path.intersects(leftPlane,topPlane,bottomPlane) ||
-            path.intersects(rightPlane,topPlane,bottomPlane)) {
+        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;
     }
 

Added: lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideSouthRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideSouthRectangle.java?rev=1675374&view=auto
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideSouthRectangle.java (added)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWideSouthRectangle.java Wed Apr 22 14:47:00 2015
@@ -0,0 +1,259 @@
+package org.apache.lucene.spatial.spatial4j.geo3d;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Bounding box wider than PI but limited on three sides (top lat,
+* left lon, right lon).
+*/
+public class GeoWideSouthRectangle extends GeoBBoxBase
+{
+    public final double topLat;
+    public final double leftLon;
+    public final double rightLon;
+      
+    public final double cosMiddleLat;
+      
+    public final GeoPoint ULHC;
+    public final GeoPoint URHC;
+    
+    public final SidedPlane topPlane;
+    public final SidedPlane leftPlane;
+    public final SidedPlane rightPlane;
+
+    public final GeoPoint[] topPlanePoints;
+    public final GeoPoint[] leftPlanePoints;
+    public final GeoPoint[] rightPlanePoints;
+
+    public final GeoPoint centerPoint;
+
+    public final EitherBound eitherBound;
+    
+    public final GeoPoint[] edgePoints = new GeoPoint[]{SOUTH_POLE};
+    
+    /** 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 double topLat, final double leftLon, double rightLon)
+    {
+        // 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(sinTopLat,sinLeftLon,cosTopLat,cosLeftLon);
+        this.URHC = new GeoPoint(sinTopLat,sinRightLon,cosTopLat,cosRightLon);
+        
+        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(sinMiddleLat,sinMiddleLon,cosMiddleLat,cosMiddleLon);
+
+        this.topPlane = new SidedPlane(centerPoint,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,SOUTH_POLE};
+        this.rightPlanePoints = new GeoPoint[]{URHC,SOUTH_POLE};
+
+        this.eitherBound = new EitherBound();
+    }
+
+    @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(newTopLat,newBottomLat,newLeftLon,newRightLon);
+    }
+
+    @Override
+    public boolean isWithin(final Vector point)
+    {
+        return topPlane.isWithin(point) &&
+          (leftPlane.isWithin(point) ||
+          rightPlane.isWithin(point));
+    }
+
+    @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 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(topPlane,notablePoints,topPlanePoints,bounds,eitherBound) ||
+          p.intersects(leftPlane,notablePoints,leftPlanePoints,bounds,topPlane) ||
+          p.intersects(rightPlane,notablePoints,rightPlanePoints,bounds,topPlane);
+    }
+
+    /** Compute longitude/latitude bounds for the shape.
+    *@param bounds is the optional input bounds object.  If this is null,
+    * a bounds object will be created.  Otherwise, the input object will be modified.
+    *@return a Bounds object describing the shape's bounds.  If the bounds cannot
+    * be computed, then return a Bounds object with noLongitudeBound,
+    * noTopLatitudeBound, and noBottomLatitudeBound.
+    */
+    @Override
+    public Bounds getBounds(Bounds bounds)
+    {
+        if (bounds == null)
+            bounds = new Bounds();
+        bounds.addLatitudeZone(topLat).noBottomLatitudeBound()
+            .addLongitudeSlice(leftLon,rightLon);
+        return bounds;
+    }
+
+    @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(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
+    public boolean equals(Object o)
+    {
+        if (!(o instanceof GeoWideSouthRectangle))
+            return false;
+        GeoWideSouthRectangle other = (GeoWideSouthRectangle)o;
+        return other.ULHC.equals(ULHC) && other.URHC.equals(URHC);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = ULHC.hashCode();
+        result = 31 * result + URHC.hashCode();
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "GeoWideSouthRectangle: {toplat="+topLat+"("+topLat*180.0/Math.PI+"), leftlon="+leftLon+"("+leftLon*180.0/Math.PI+"), rightlon="+rightLon+"("+rightLon*180.0/Math.PI+")}";
+    }
+
+    protected class EitherBound implements Membership {
+        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);
+        }
+    }
+}
+  
+

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWorld.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWorld.java?rev=1675374&r1=1675373&r2=1675374&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWorld.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoWorld.java Wed Apr 22 14:47:00 2015
@@ -59,7 +59,7 @@ public class GeoWorld extends GeoBBoxBas
     }
       
     @Override
-    public boolean intersects(final Plane p, final Membership... bounds)
+    public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds)
     {
         return false;
     }

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Plane.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Plane.java?rev=1675374&r1=1675373&r2=1675374&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Plane.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Plane.java Wed Apr 22 14:47:00 2015
@@ -216,7 +216,7 @@ public class Plane extends Vector
 
         // Now compute latitude min/max points
         if (!boundsInfo.checkNoTopLatitudeBound() || !boundsInfo.checkNoBottomLatitudeBound()) {
-            if ((Math.abs(A) >= 1e-10 || Math.abs(B) >= 1e-10)) {
+            if ((Math.abs(A) >= MINIMUM_RESOLUTION || Math.abs(B) >= MINIMUM_RESOLUTION)) {
                 //System.out.println("A = "+A+" B = "+B+" C = "+C+" D = "+D);
                 // sin (phi) = z
                 // cos (theta - phi) = D
@@ -359,11 +359,11 @@ public class Plane extends Vector
             double b;
             double c;
             
-            if (Math.abs(C) < 1e-10) {
+            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) >= 1e-10) {
+                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.
@@ -432,7 +432,6 @@ public class Plane extends Vector
                         double sqrtClause = b * b - 4.0 * a * c;
 
                         if (sqrtClause >= 0.0) {
-
                             if (sqrtClause == 0.0) {
                                 double x0 = -b / (2.0 * a);
                                 double y0 = (- D - A * x0) / B;
@@ -560,7 +559,7 @@ public class Plane extends Vector
                                 addPoint(boundsInfo, bounds, x0a, y0a, z0a);
                                 addPoint(boundsInfo, bounds, x0b, y0b, z0b);
                             }
-                        }                        
+                        }
 
                     } else {
                         //System.out.println("Using the x quadratic");
@@ -588,7 +587,6 @@ public class Plane extends Vector
                         //System.out.println("sqrtClause="+sqrtClause);
                         
                         if (sqrtClause >= 0.0) {
-                            
                             if (sqrtClause == 0.0) {
                                 //System.out.println("One solution");
                                 double x0 = -b / (2.0 * a);
@@ -634,13 +632,44 @@ public class Plane extends Vector
     /** Determine whether the plane intersects another plane within the
      * bounds provided.
      *@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 Plane q, final Membership[] bounds, final Membership... moreBounds) {
+    public boolean intersects(final Plane q, final GeoPoint[] notablePoints, final GeoPoint[] moreNotablePoints, final Membership[] bounds, final Membership... moreBounds) {
+        // 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 (equals(q)) {
+            // 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))
+                    return true;
+            }
+            for (GeoPoint p : moreNotablePoints) {
+                if (meetsAllBounds(p,bounds,moreBounds))
+                    return true;
+            }
+            return false;
+        }
         return findIntersections(q,bounds,moreBounds).length > 0;
     }
+
+    protected static boolean meetsAllBounds(final GeoPoint p, final Membership[] bounds, final Membership[] moreBounds) {
+        for (final Membership bound : bounds) {
+            if (!bound.isWithin(p))
+                return false;
+        }
+        for (final Membership bound : moreBounds) {
+            if (!bound.isWithin(p))
+                return false;
+        }
+        return true;
+    }
     
     /** Find a sample point on the intersection between two planes and the unit sphere.
     */

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/SidedPlane.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/SidedPlane.java?rev=1675374&r1=1675373&r2=1675374&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/SidedPlane.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/SidedPlane.java Wed Apr 22 14:47:00 2015
@@ -79,9 +79,10 @@ public class SidedPlane extends Plane im
     @Override
     public boolean isWithin(Vector point)
     {
-        double sigNum = Math.signum(evaluate(point));
-        if (sigNum == 0.0)
+        double evalResult = evaluate(point);
+        if (Math.abs(evalResult) < MINIMUM_RESOLUTION)
             return true;
+        double sigNum = Math.signum(evalResult);
         return sigNum == this.sigNum;
     }
 
@@ -94,7 +95,10 @@ public class SidedPlane extends Plane im
     @Override
     public boolean isWithin(double x, double y, double z)
     {
-        double sigNum = Math.signum(this.x * x + this.y * y + this.z * z);
+        double evalResult = this.x * x + this.y * y + this.z * z;
+        if (Math.abs(evalResult) < MINIMUM_RESOLUTION)
+            return true;
+        double sigNum = Math.signum(evalResult);
         return sigNum == this.sigNum;
     }
     

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Vector.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Vector.java?rev=1675374&r1=1675373&r2=1675374&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Vector.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Vector.java Wed Apr 22 14:47:00 2015
@@ -21,6 +21,10 @@ package org.apache.lucene.spatial.spatia
  * going through the origin. */
 public class Vector
 {
+    /** Values that are all considered to be essentially zero have a magnitude
+    * less than this. */
+    public static final double MINIMUM_RESOLUTION = 1e-15;
+    
     public final double x;
     public final double y;
     public final double z;
@@ -56,13 +60,31 @@ public class Vector
      */
     public Vector normalize() {
         double denom = magnitude();
-        if (denom < 1e-10)
+        if (denom < MINIMUM_RESOLUTION)
             // Degenerate, can't normalize
             return null;
         double normFactor = 1.0/denom;
         return new Vector(x*normFactor,y*normFactor,z*normFactor);
     }
     
+    /** Evaluate a vector (dot product) and check for "zero".
+     *@param v is the vector to evaluate.
+     *@return true if the evaluation yielded zero.
+     */
+    public boolean evaluateIsZero(final Vector v) {
+        return Math.abs(evaluate(v)) < MINIMUM_RESOLUTION;
+    }
+    
+    /** Evaluate a vector (do a dot product) snd check for "zero".
+     *@param x is the x value of the vector to evaluate.
+     *@param y is the x value of the vector to evaluate.
+     *@param z is the x value of the vector to evaluate.
+     *@return true if the evaluation yielded zero.
+     */
+    public boolean evaluateIsZero(final double x, final double y, final double z) {
+        return Math.abs(evaluate(x,y,z)) < MINIMUM_RESOLUTION;
+    }
+
     /** Evaluate a vector (do a dot product).
      *@param v is the vector to evaluate.
      *@return the result.

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/Geo3dRptTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/Geo3dRptTest.java?rev=1675374&r1=1675373&r2=1675374&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/Geo3dRptTest.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/Geo3dRptTest.java Wed Apr 22 14:47:00 2015
@@ -21,12 +21,10 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
-import com.carrotsearch.randomizedtesting.annotations.Seed;
+import com.carrotsearch.randomizedtesting.annotations.Repeat;
 import com.spatial4j.core.context.SpatialContext;
 import com.spatial4j.core.shape.Point;
-import com.spatial4j.core.shape.Rectangle;
 import com.spatial4j.core.shape.Shape;
-import com.spatial4j.core.shape.SpatialRelation;
 import org.apache.lucene.spatial.composite.CompositeSpatialStrategy;
 import org.apache.lucene.spatial.prefix.RandomSpatialOpStrategyTestCase;
 import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy;
@@ -34,7 +32,6 @@ import org.apache.lucene.spatial.prefix.
 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.spatial.spatial4j.geo3d.GeoBBox;
 import org.apache.lucene.spatial.spatial4j.geo3d.GeoBBoxFactory;
 import org.apache.lucene.spatial.spatial4j.geo3d.GeoCircle;
 import org.apache.lucene.spatial.spatial4j.geo3d.GeoPath;
@@ -80,42 +77,14 @@ public class Geo3dRptTest extends Random
   }
 
   @Test
-  //@Repeat(iterations = 2000)
-  @Seed("B808B88D6F8E285C")
+  @Repeat(iterations = 2000)
+  //@Seed("B808B88D6F8E285C")
   public void testOperations() throws IOException {
     setupStrategy();
 
     testOperationRandomShapes(SpatialOperation.Intersects);
   }
 
-  @Test
-  public void testBigCircleFailure() throws IOException {
-    Rectangle rect = ctx.makeRectangle(-162, 89, -46, 38);
-    GeoCircle rawShape = new GeoCircle(-9 * DEGREES_TO_RADIANS, 134 * DEGREES_TO_RADIANS, 159 * DEGREES_TO_RADIANS);
-    Shape shape = new Geo3dShape(rawShape, ctx);
-    assertTrue(rect.relate(shape).intersects() == false);     //DWS: unsure if this is correct or not but passes
-    //since they don't intersect, then the following cell rect can't be WITHIN the circle
-    final Rectangle cellRect = ctx.makeRectangle(-11.25, 0, 0, 5.625);
-    assert cellRect.relate(rect).intersects();
-    assertTrue(cellRect.relate(shape) != SpatialRelation.WITHIN);
-  }
-
-  @Test
-  public void testWideRectFailure() throws IOException {
-    Rectangle rect = ctx.makeRectangle(-29, 9, 16, 25);
-    final GeoBBox geoBBox = GeoBBoxFactory.makeGeoBBox(
-        74 * DEGREES_TO_RADIANS, -31 * DEGREES_TO_RADIANS, -29 * DEGREES_TO_RADIANS, -45 * DEGREES_TO_RADIANS);
-    Shape shape = new Geo3dShape(geoBBox, ctx);
-    //Rect(minX=-22.5,maxX=-11.25,minY=11.25,maxY=16.875)
-    //since they don't intersect, then the following cell rect can't be WITHIN the geo3d shape
-    final Rectangle cellRect = ctx.makeRectangle(-22.5, -11.25, 11.25, 16.875);
-    assert cellRect.relate(rect).intersects();
-    assertTrue(rect.relate(shape).intersects() == false);
-    assertTrue(cellRect.relate(shape) != SpatialRelation.WITHIN);
-//    setupStrategy();
-//    testOperation(rect, SpatialOperation.Intersects, shape, false);
-  }
-
   private Shape makeTriangle(double x1, double y1, double x2, double y2, double x3, double y3) {
     final List<GeoPoint> geoPoints = new ArrayList<>();
     geoPoints.add(new GeoPoint(y1 * DEGREES_TO_RADIANS, x1 * DEGREES_TO_RADIANS));
@@ -159,7 +128,7 @@ public class Geo3dRptTest extends Random
     case 1: {
         // Circles
         while (true) {
-          final int circleRadius = random().nextInt(180);
+          final int circleRadius = random().nextInt(179) + 1;
           final Point point = randomPoint();
           try {
             final GeoShape shape = new GeoCircle(point.getY() * DEGREES_TO_RADIANS, point.getX() * DEGREES_TO_RADIANS,
@@ -188,6 +157,7 @@ public class Geo3dRptTest extends Random
               lrhcPoint.getY() * DEGREES_TO_RADIANS,
               ulhcPoint.getX() * DEGREES_TO_RADIANS,
               lrhcPoint.getX() * DEGREES_TO_RADIANS);
+            //System.err.println("Trial rectangle shape: "+shape);
             return new Geo3dShape(shape, ctx);
           } catch (IllegalArgumentException e) {
             // This is what happens when we create a shape that is invalid.  Although it is conceivable that there are cases where