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/05/01 20:49:49 UTC

svn commit: r1677205 - in /lucene/dev/branches/lucene6196/lucene/spatial/src: java/org/apache/lucene/spatial/spatial4j/geo3d/ test/org/apache/lucene/spatial/spatial4j/ test/org/apache/lucene/spatial/spatial4j/geo3d/

Author: dsmiley
Date: Fri May  1 18:49:49 2015
New Revision: 1677205

URL: http://svn.apache.org/r1677205
Log:
LUCENE-6196: committing Karl's latest patch
https://reviews.apache.org/r/33509/ (diff #6)

Modified:
    lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Bounds.java
    lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoConvexPolygon.java
    lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPath.java
    lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPoint.java
    lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Plane.java
    lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Vector.java
    lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeRectRelationTest.java
    lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoBBoxTest.java
    lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoPathTest.java
    lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/PlaneTest.java

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Bounds.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Bounds.java?rev=1677205&r1=1677204&r2=1677205&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Bounds.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/Bounds.java Fri May  1 18:49:49 2015
@@ -187,7 +187,8 @@ public class Bounds
         double testRightLongitude = rightLongitude;
         if (testRightLongitude < leftLongitude)
             testRightLongitude += Math.PI * 2.0;
-        if (testRightLongitude - leftLongitude >= Math.PI * 2.0) {
+        // If the bound exceeds 180 degrees, we know we could have screwed up.
+        if (testRightLongitude - leftLongitude >= Math.PI) {
             noLongitudeBound = true;
             leftLongitude = null;
             rightLongitude = null;
@@ -244,7 +245,7 @@ public class Bounds
         double testRightLongitude = rightLongitude;
         if (testRightLongitude < leftLongitude)
             testRightLongitude += Math.PI * 2.0;
-        if (testRightLongitude - leftLongitude >= Math.PI * 2.0) {
+        if (testRightLongitude - leftLongitude >= Math.PI) {
             noLongitudeBound = true;
             leftLongitude = null;
             rightLongitude = null;

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoConvexPolygon.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoConvexPolygon.java?rev=1677205&r1=1677204&r2=1677205&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoConvexPolygon.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoConvexPolygon.java Fri May  1 18:49:49 2015
@@ -229,7 +229,7 @@ public class GeoConvexPolygon extends Ge
             edge.recordBounds(bounds,membershipBounds);
         }
 
-        if (fullDistance >= Math.PI * 0.5) {
+        if (fullDistance >= Math.PI) {
             // We can't reliably assume that bounds did its longitude calculation right, so we force it to be unbounded.
             bounds.noLongitudeBound();
         }

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPath.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPath.java?rev=1677205&r1=1677204&r2=1677205&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPath.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPath.java Fri May  1 18:49:49 2015
@@ -677,7 +677,7 @@ public class GeoPath extends GeoBaseExte
             lowerConnectingPlane.recordBounds(bounds, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
             startCutoffPlane.recordBounds(bounds, endCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
             endCutoffPlane.recordBounds(bounds, startCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
-            if (fullDistance >= Math.PI * 0.5) {
+            if (fullDistance >= Math.PI) {
                 // Too large a segment basically means that we can confuse the Bounds object.  Specifically, if our span exceeds 180 degrees
                 // in longitude (which even a segment whose actual length is less than that might if it goes close to a pole).
                 // Unfortunately, we can get arbitrarily close to the pole, so this may still not work in all cases.

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPoint.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPoint.java?rev=1677205&r1=1677204&r2=1677205&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPoint.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/java/org/apache/lucene/spatial/spatial4j/geo3d/GeoPoint.java Fri May  1 18:49:49 2015
@@ -38,7 +38,7 @@ public class GeoPoint extends Vector
           
     public double arcDistance(final GeoPoint v)
     {
-        return Tools.safeAcos(evaluate(v));
+        return Tools.safeAcos(dotProduct(v));
     }
 
 }

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=1677205&r1=1677204&r2=1677205&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 Fri May  1 18:49:49 2015
@@ -27,6 +27,13 @@ public class Plane extends Vector
     
     public final double D;
   
+    /** Construct a plane with all four coefficients defined.
+    */
+    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).
@@ -68,9 +75,8 @@ public class Plane extends Vector
      *@param v is the vector.
      *@return the result of the evaluation.
      */
-    @Override
     public double evaluate(final Vector v) {
-        return super.evaluate(v) + D;
+        return dotProduct(v) + D;
     }
 
     /** Evaluate the plane equation for a given point, as represented
@@ -78,9 +84,8 @@ public class Plane extends Vector
      *@param x,y,z is the vector.
      *@return the result of the evaluation.
      */
-    @Override
     public double evaluate(final double x, final double y, final double z) {
-        return super.evaluate(x,y,z) + D;
+        return dotProduct(x,y,z) + D;
     }
 
     /** Evaluate the plane equation for a given point, as represented
@@ -88,7 +93,6 @@ public class Plane extends Vector
      *@param v is the vector.
      *@return true if the result is on the plane.
      */
-    @Override
     public boolean evaluateIsZero(final Vector v) {
         return Math.abs(evaluate(v)) < MINIMUM_RESOLUTION;
     }
@@ -98,7 +102,6 @@ public class Plane extends Vector
      *@param x,y,z is the vector.
      *@return true if the result is on the plane.
      */
-    @Override
     public boolean evaluateIsZero(final double x, final double y, final double z) {
         return Math.abs(evaluate(x,y,z)) < MINIMUM_RESOLUTION;
     }
@@ -113,6 +116,159 @@ public class Plane extends Vector
         return new Plane(normVect,this.D);
     }
 
+    /** 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.
+    */
+    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 beginAngle;
+        
+        double newEndAngle = endAngle;
+        while (newEndAngle < startAngle)  {
+            newEndAngle += Math.PI * 2.0;
+        }
+        
+        if (newEndAngle - startAngle <= Math.PI) {
+            delta = newEndAngle - startAngle;
+            beginAngle = startAngle;
+        } else {
+            double newStartAngle = startAngle;
+            while (newStartAngle < endAngle) {
+                newStartAngle += Math.PI * 2.0;
+            }
+            delta = newStartAngle - endAngle;
+            beginAngle = 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.
+    */
+    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.
+    */
+    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);
+    }
+    
     /** Find the intersection points between two planes, given a set of bounds.
     *@param q is the plane to intersect with.
     *@param bounds is the set of bounds.
@@ -823,14 +979,26 @@ public class Plane extends Vector
     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_SQUARED)
+        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_SQUARED)
+        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_SQUARED)
+        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.  
+        // 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);
     }

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=1677205&r1=1677204&r2=1677205&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 Fri May  1 18:49:49 2015
@@ -70,42 +70,24 @@ public class Vector
         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.
+    /** Do a dot product.
+     *@param v is the vector to multiply.
      *@return the result.
      */
-    public double evaluate(final Vector v) {
+    public double dotProduct(final Vector v) {
         return this.x * v.x + this.y * v.y + this.z * v.z;
     }
 
-    /** Evaluate a vector (do a dot product).
-     *@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.
+    /** 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 evaluate(final double x, final double y, final double z) {
+    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.
@@ -125,6 +107,48 @@ public class Vector
         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.
@@ -182,7 +206,7 @@ public class Vector
      *@return the square of the normal distance.
      */
     public double normalDistanceSquared(final Vector v) {
-        double t = x*v.x + y*v.y + z*v.z;
+        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;
@@ -198,7 +222,7 @@ public class Vector
      *@return the square of the normal distance.
      */
     public double normalDistanceSquared(final double x, final double y, final double z) {
-        double t = this.x*x + this.y*y + this.z*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;

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeRectRelationTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeRectRelationTest.java?rev=1677205&r1=1677204&r2=1677205&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeRectRelationTest.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/Geo3dShapeRectRelationTest.java Fri May  1 18:49:49 2015
@@ -56,39 +56,55 @@ public class Geo3dShapeRectRelationTest
   @Test
   public void testFailure() {
       /*
-   [junit4]   1> S-R Rel: {}, Shape {}, Rectangle {} [INTERSECTS, Geo3dShape{GeoCompositeMembershipShape: {[
-   GeoConvexPolygon: {
-   points=[
-     [X=0.03206699943821901, Y=-0.7556330442094724, Z=0.6542097599743943], 
-     [X=-0.2848733212046893, Y=-0.9533780638748927, Z=0.09958643576296423], 
-     [X=0.37929990916639644, Y=0.9241954620264722, Z=0.044657887053005746]] 
-   edges={
-     [A=0.5484584327149066, B=-0.18956034526809354, C=-0.2458316687546487, D=0.0, side=1.0] internal? false; 
-     [A=-0.13461318190686059, B=0.05049496664187115, C=0.09833758231919826, D=0.0, side=1.0] internal? false; 
-     [A=0.6383626665235883, B=-0.246709658095017, C=-0.31624772039338794, D=0.0, side=1.0] internal? false; }}]}},
-     X=0.03206699943821901, Y=-0.7556330442094724, Z=0.6542097599743943
-   Rect(minX=-52.0,maxX=50.0,minY=58.0,maxY=68.0)](no slf4j subst; sorry)
-
+   [junit4]   1> S-R Rel: {}, Shape {}, Rectangle {} [WITHIN, Geo3dShape{GeoCompositeMembershipShape: {[
+    GeoConvexPolygon: {points=[
+      [X=0.35168818443386646, Y=-0.19637966197066342, Z=0.9152870857244183],
+      [X=0.5003343189532654, Y=0.522128543226148, Z=0.6906861469771293], 
+      [X=0.8344549994139991, Y=0.216175219373972, Z=0.5069054433339593]] 
+    edges={
+      [A=-0.6135342247741855, B=0.21504338363863665, C=0.28188192383666794, D=0.0, side=-1.0] internal? false;
+      [A=0.11536057134002048, B=0.32272431860685813, C=-0.3275328920717585, D=0.0, side=-1.0] internal? false;
+      [A=0.29740830615965186, B=-0.5854932295360462, C=-0.2398962611358763, D=0.0, side=-1.0] internal? false; }}]}}, 
+    Rect(minX=-30.0,maxX=62.0,minY=30.0,maxY=88.0)](no slf4j subst; sorry)
+   [junit4] FAILURE 1.85s J2 | Geo3dShapeRectRelationTest.testGeoPolygonRect <<<
+   [junit4]    > Throwable #1: java.lang.AssertionError: Rect(minX=-30.0,maxX=62.0,minY=30.0,maxY=88.0) intersect Pt(x=82.75500168892472,y=34.2730264413182)
+   [junit4]    > 	at __randomizedtesting.SeedInfo.seed([3EBD2127AF6641F7:3A64BDAC8843B64]:0)
+   [junit4]    > 	at org.apache.lucene.spatial.spatial4j.RandomizedShapeTest._assertIntersect(RandomizedShapeTest.java:167)
+   [junit4]    > 	at org.apache.lucene.spatial.spatial4j.RandomizedShapeTest.assertRelation(RandomizedShapeTest.java:152)
+   [junit4]    > 	at org.apache.lucene.spatial.spatial4j.RectIntersectionTestHelper.testRelateWithRectangle(RectIntersectionTestHelper.java:105)
+   [junit4]    > 	at org.apache.lucene.spatial.spatial4j.Geo3dShapeRectRelationTest.testGeoPolygonRect(Geo3dShapeRectRelationTest.java:219)
     */
-      final GeoBBox rect = GeoBBoxFactory.makeGeoBBox(68 * RADIANS_PER_DEGREE, 58 * RADIANS_PER_DEGREE, -52 * RADIANS_PER_DEGREE, 50 * RADIANS_PER_DEGREE);
+      final GeoBBox rect = GeoBBoxFactory.makeGeoBBox(88 * RADIANS_PER_DEGREE, 30 * RADIANS_PER_DEGREE, -30 * RADIANS_PER_DEGREE, 62 * RADIANS_PER_DEGREE);
       final List<GeoPoint> points = new ArrayList<GeoPoint>();
-      points.add(new GeoPoint(40.8597568993 * RADIANS_PER_DEGREE, -87.5699819016 * RADIANS_PER_DEGREE));
-      points.add(new GeoPoint(5.71535611517 * RADIANS_PER_DEGREE, -106.636363741 * RADIANS_PER_DEGREE));
-      points.add(new GeoPoint(2.55955969779 * RADIANS_PER_DEGREE, 67.6862179901 * RADIANS_PER_DEGREE));
+      points.add(new GeoPoint(66.2465299717 * RADIANS_PER_DEGREE, -29.1786158537 * RADIANS_PER_DEGREE));
+      points.add(new GeoPoint(43.684447915 * RADIANS_PER_DEGREE, 46.2210986329 * RADIANS_PER_DEGREE));
+      points.add(new GeoPoint(30.4579218227 * RADIANS_PER_DEGREE, 14.5238410082 * RADIANS_PER_DEGREE));
       final GeoShape path = GeoPolygonFactory.makeGeoPolygon(points,0);
+    
+      final GeoPoint point = new GeoPoint(34.2730264413182 * RADIANS_PER_DEGREE, 82.75500168892472 * RADIANS_PER_DEGREE);
       
-      System.err.println("Rectangle = "+rect+"; path = "+path);
+      System.err.println("Rectangle = "+rect+"; path = "+path+"; point = "+point);
 
-      // Edges intersect == OVERLAP.  This seems reasonable... between points 2 and 3 the path could well cross.
-      assertFalse(GeoArea.DISJOINT == rect.getRelationship(path));
-      
-      final GeoBBox pathBounds = getBoundingBox(path);
-      // Path bounds go around the back side of the world rather than the front.  The actual path goes around the front.  This is I think what the problem is.
-      System.err.println("Path bounds = "+pathBounds);
-      assertFalse(GeoArea.DISJOINT == rect.getRelationship(pathBounds));
+      /*
+         [junit4]   2> Rectangle = GeoRectangle: {toplat=1.53588974175501(87.99999999999999), bottomlat=0.5235987755982988(29.999999999999996), leftlon=-0.5235987755982988(-29.999999999999996), rightlon=1.0821041362364843(62.0)};
+         path = GeoCompositeMembershipShape: {[GeoConvexPolygon: {points=[
+         [X=0.3516881844340107, Y=-0.1963796619709742, Z=0.9152870857242963], 
+         [X=0.500334318953081, Y=0.5221285432268337, Z=0.6906861469767445], 
+         [X=0.8344549994140144, Y=0.21617521937373424, Z=0.5069054433340355]] 
+         edges={[A=-0.6135342247748885, B=0.21504338363844255, C=0.28188192383710364, D=0.0, side=-1.0] internal? false;
+         [A=0.1153605713406553, B=0.32272431860660283, C=-0.3275328920724975, D=0.0, side=-1.0] internal? false;
+         [A=0.29740830615958036, B=-0.5854932295358584, C=-0.2398962611360862, D=0.0, side=-1.0] internal? false; }}]};
+         point = [X=0.10421465978661167, Y=0.8197657811637465, Z=0.5631370780889439]
+        */
+      // Apparently the rectangle thinks the polygon is completely within it... "shape inside rectangle"
+      assertTrue(GeoArea.WITHIN == rect.getRelationship(path));
+
+      // Point is within path? Apparently not...
+      assertFalse(path.isWithin(point));
+
+      // If it is within the path, it must be within the rectangle, and similarly visa versa
+      assertFalse(rect.isWithin(point));
       
-      final GeoBBox rectBounds = getBoundingBox(rect);
-      assertFalse(GeoArea.DISJOINT == rectBounds.getRelationship(pathBounds));
   }
 
   protected static GeoBBox getBoundingBox(final GeoShape path) {

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoBBoxTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoBBoxTest.java?rev=1677205&r1=1677204&r2=1677205&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoBBoxTest.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoBBoxTest.java Fri May  1 18:49:49 2015
@@ -17,13 +17,15 @@ package org.apache.lucene.spatial.spatia
  * limitations under the License.
  */
 
-import static org.junit.Assert.*;
-
-import java.util.List;
 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;
@@ -145,11 +147,11 @@ public class GeoBBoxTest {
         c = GeoBBoxFactory.makeGeoBBox(0.0,-Math.PI * 0.25, 1.0, -1.0);
 
         b = c.getBounds(null);
-        assertFalse(b.checkNoLongitudeBound());
+        assertTrue(b.checkNoLongitudeBound());
         assertFalse(b.checkNoTopLatitudeBound());
         assertFalse(b.checkNoBottomLatitudeBound());
-        assertEquals(1.0,b.getLeftLongitude(),0.000001);
-        assertEquals(-1.0,b.getRightLongitude(),0.000001);
+        //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);
 
@@ -165,22 +167,22 @@ public class GeoBBoxTest {
         c = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, 1.0, -1.0);
 
         b = c.getBounds(null);
-        assertFalse(b.checkNoLongitudeBound());
+        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,b.getLeftLongitude(),0.000001);
+        //assertEquals(-1.0,b.getRightLongitude(),0.000001);
 
         // Check wide variants of rectangle and longitude slice
 
         c = GeoBBoxFactory.makeGeoBBox(0.0,-Math.PI * 0.25, -Math.PI+0.1, Math.PI-0.1);
 
         b = c.getBounds(null);
-        assertFalse(b.checkNoLongitudeBound());
+        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.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);
 
@@ -198,11 +200,11 @@ public class GeoBBoxTest {
         c = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, -Math.PI+0.1, Math.PI-0.1);
 
         b = c.getBounds(null);
-        assertFalse(b.checkNoLongitudeBound());
+        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);
+        //assertEquals(-Math.PI+0.1,b.getLeftLongitude(),0.000001);
+        //assertEquals(Math.PI-0.1,b.getRightLongitude(),0.000001);
 
         c = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, Math.PI-0.1, -Math.PI+0.1);
 
@@ -243,11 +245,11 @@ public class GeoBBoxTest {
         b = new Bounds();
         b = c1.getBounds(b);
         b = c2.getBounds(b);
-        assertFalse(b.checkNoLongitudeBound());
+        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);
+        //assertEquals(-Math.PI,b.getLeftLongitude(),0.000001);
+        //assertEquals(Math.PI*0.5,b.getRightLongitude(),0.000001);
 
         c1 = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, -Math.PI * 0.5, 0.0);
         c2 = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI);
@@ -255,11 +257,11 @@ public class GeoBBoxTest {
         b = new Bounds();
         b = c1.getBounds(b);
         b = c2.getBounds(b);
-        assertFalse(b.checkNoLongitudeBound());
+        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);
+        //assertEquals(-Math.PI * 0.5,b.getLeftLongitude(),0.000001);
+        //assertEquals(Math.PI,b.getRightLongitude(),0.000001);
 
     }
 

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoPathTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoPathTest.java?rev=1677205&r1=1677204&r2=1677205&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoPathTest.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/GeoPathTest.java Fri May  1 18:49:49 2015
@@ -178,6 +178,7 @@ public class GeoPathTest {
         assertEquals(0.4046919,b.getRightLongitude(),0.000001);
         assertEquals(-0.3999999,b.getMinLatitude(),0.000001);
         assertEquals(0.3999999,b.getMaxLatitude(),0.000001);
+
     }
 
 }

Modified: lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/PlaneTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/PlaneTest.java?rev=1677205&r1=1677204&r2=1677205&view=diff
==============================================================================
--- lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/PlaneTest.java (original)
+++ lucene/dev/branches/lucene6196/lucene/spatial/src/test/org/apache/lucene/spatial/spatial4j/geo3d/PlaneTest.java Fri May  1 18:49:49 2015
@@ -42,7 +42,23 @@ public class PlaneTest {
         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));
+        }
+    }
 }