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

svn commit: r1695700 - in /lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d: GeoAreaFactory.java PlanetModel.java XYZSolid.java XYdZSolid.java XdYZSolid.java dXYZSolid.java dXdYdZSolid.java

Author: mikemccand
Date: Thu Aug 13 12:29:29 2015
New Revision: 1695700

URL: http://svn.apache.org/r1695700
Log:
LUCENE-6699: another iteration on degenerate solids

Added:
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYdZSolid.java   (with props)
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XdYZSolid.java   (with props)
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXYZSolid.java   (with props)
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXdYdZSolid.java   (with props)
Modified:
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoAreaFactory.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PlanetModel.java
    lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZSolid.java

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoAreaFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoAreaFactory.java?rev=1695700&r1=1695699&r2=1695700&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoAreaFactory.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoAreaFactory.java Thu Aug 13 12:29:29 2015
@@ -50,8 +50,36 @@ public class GeoAreaFactory {
    * @param maxZ is the max Z boundary
    */
   public static GeoArea makeGeoArea(final PlanetModel planetModel, final double minX, final double maxX, final double minY, final double maxY, final double minZ, final double maxZ) {
+    if (Math.abs(maxX - minX) < Vector.MINIMUM_RESOLUTION) {
+      if (Math.abs(maxY - minY) < Vector.MINIMUM_RESOLUTION) {
+        if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
+          return new dXdYdZSolid(planetModel, minX, minY, minZ);
+        } else {
+          // nocommit - more here, degenerate in X and Y
+          throw new IllegalArgumentException("degenerate in X,Y");
+        }
+      } else {
+        if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
+          // nocommit -  more here, degenerate in X and Z
+          throw new IllegalArgumentException("degenerate in X,Z");
+        } else {
+          return new dXYZSolid(planetModel, minX, minY, maxY, minZ, maxZ);
+        }
+      }
+    }
+    if (Math.abs(maxY - minY) < Vector.MINIMUM_RESOLUTION) {
+      if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
+        // nocommit - more here, degenerate in Y and Z
+          throw new IllegalArgumentException("degenerate in Y,Z");
+      } else {
+        return new XdYZSolid(planetModel, minX, maxX, minY, minZ, maxZ);
+      }
+    }
+    if (Math.abs(maxZ - minZ) < Vector.MINIMUM_RESOLUTION) {
+      return new XYdZSolid(planetModel, minX, maxX, minY, maxY, minZ);
+    }
     // nocommit - handle degenerate cases explicitly
-    return new XYZSolid(planetModel, minX, maxY, minY, maxY, minZ, maxZ);
+    return new XYZSolid(planetModel, minX, maxX, minY, maxY, minZ, maxZ);
   }
   
 }

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PlanetModel.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PlanetModel.java?rev=1695700&r1=1695699&r2=1695700&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PlanetModel.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PlanetModel.java Thu Aug 13 12:29:29 2015
@@ -139,6 +139,25 @@ public class PlanetModel {
     return this.c;
   }
 
+  /** Check if point is on surface.
+   * @param v is the point to check.
+   * @return true if the point is on the planet surface.
+   */
+  public boolean pointOnSurface(final Vector v) {
+    return pointOnSurface(v.x, v.y, v.z);
+  }
+  
+  /** Check if point is on surface.
+   * @param x is the x coord.
+   * @param y is the y coord.
+   * @param z is the z coord.
+   */
+  public boolean pointOnSurface(final double x, final double y, final double z) {
+    // Equation of planet surface is:
+    // x^2 / a^2 + y^2 / b^2 + z^2 / c^2 - 1 = 0
+    return Math.abs((x * x + y * y) * inverseAb * inverseAb + z * z * inverseC * inverseC - 1.0) < Vector.MINIMUM_RESOLUTION_SQUARED;
+  }
+  
   /** Compute surface distance between two points.
    * @param p1 is the first point.
    * @param p2 is the second point.

Modified: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZSolid.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZSolid.java?rev=1695700&r1=1695699&r2=1695700&view=diff
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZSolid.java (original)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZSolid.java Thu Aug 13 12:29:29 2015
@@ -60,7 +60,6 @@ public class XYZSolid extends BaseXYZSol
   protected final GeoPoint[] notableMaxZPoints;
 
   /**
-   * Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
    *@param planetModel is the planet model.
    *@param minX is the minimum X value.
    *@param maxX is the maximum X value.
@@ -316,7 +315,7 @@ public class XYZSolid extends BaseXYZSol
     }
     if (!isWholeWorld) {
       return other.minXPlane.equals(minXPlane) &&
-        other.maxXPlane.equals(maxYPlane) &&
+        other.maxXPlane.equals(maxXPlane) &&
         other.minYPlane.equals(minYPlane) &&
         other.maxYPlane.equals(maxYPlane) &&
         other.minZPlane.equals(minZPlane) &&

Added: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYdZSolid.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYdZSolid.java?rev=1695700&view=auto
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYdZSolid.java (added)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYdZSolid.java Thu Aug 13 12:29:29 2015
@@ -0,0 +1,206 @@
+package org.apache.lucene.geo3d;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in Z
+ *
+ * @lucene.internal
+ */
+public class XYdZSolid extends BaseXYZSolid {
+
+  /** Min-X plane */
+  protected final SidedPlane minXPlane;
+  /** Max-X plane */
+  protected final SidedPlane maxXPlane;
+  /** Min-Y plane */
+  protected final SidedPlane minYPlane;
+  /** Max-Y plane */
+  protected final SidedPlane maxYPlane;
+  /** Z plane */
+  protected final Plane zPlane;
+  
+  /** These are the edge points of the shape, which are defined to be at least one point on
+   * each surface area boundary.  In the case of a solid, this includes points which represent
+   * the intersection of XYZ bounding planes and the planet, as well as points representing
+   * the intersection of single bounding planes with the planet itself.
+   */
+  protected final GeoPoint[] edgePoints;
+
+  /** Notable points for ZPlane */
+  protected final GeoPoint[] notableZPoints;
+
+  /**
+   *@param planetModel is the planet model.
+   *@param minX is the minimum X value.
+   *@param maxX is the maximum X value.
+   *@param minY is the minimum Y value.
+   *@param maxY is the maximum Y value.
+   *@param Z is the Z value.
+   */
+  public XYdZSolid(final PlanetModel planetModel,
+    final double minX,
+    final double maxX,
+    final double minY,
+    final double maxY,
+    final double Z) {
+    super(planetModel);
+    // Argument checking
+    if (maxX - minX < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("X values in wrong order or identical");
+    if (maxY - minY < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("Y values in wrong order or identical");
+
+    final double worldMinX = planetModel.getMinimumXValue();
+    final double worldMaxX = planetModel.getMaximumXValue();
+    final double worldMinY = planetModel.getMinimumYValue();
+    final double worldMaxY = planetModel.getMaximumYValue();
+    final double worldMinZ = planetModel.getMinimumZValue();
+    final double worldMaxZ = planetModel.getMaximumZValue();
+    
+    // Construct the planes
+    minXPlane = new SidedPlane(maxX,0.0,0.0,xUnitVector,-minX);
+    maxXPlane = new SidedPlane(minX,0.0,0.0,xUnitVector,-maxX);
+    minYPlane = new SidedPlane(0.0,maxY,0.0,yUnitVector,-minY);
+    maxYPlane = new SidedPlane(0.0,minY,0.0,yUnitVector,-maxY);
+    zPlane = new Plane(zUnitVector,-Z);
+      
+    // We need at least one point on the planet surface for each manifestation of the shape.
+    // There can be up to 2 (on opposite sides of the world).  But we have to go through
+    // 4 combinations of adjacent planes in order to find out if any have 2 intersection solution.
+    // Typically, this requires 4 square root operations. 
+    final GeoPoint[] minXZ = minXPlane.findIntersections(planetModel,zPlane,maxXPlane,minYPlane,maxYPlane);
+    final GeoPoint[] maxXZ = maxXPlane.findIntersections(planetModel,zPlane,minXPlane,minYPlane,maxYPlane);
+    final GeoPoint[] minYZ = minYPlane.findIntersections(planetModel,zPlane,maxYPlane,minXPlane,maxXPlane);
+    final GeoPoint[] maxYZ = maxYPlane.findIntersections(planetModel,zPlane,minYPlane,minXPlane,maxXPlane);
+      
+    notableZPoints = glueTogether(minXZ, maxXZ, minYZ, maxYZ);
+
+    // Now, compute the edge points.
+    // This is the trickiest part of setting up an XYZSolid.  We've computed intersections already, so
+    // we'll start there.  We know that at most there will be two disconnected shapes on the planet surface.
+    // But there's also a case where exactly one plane slices through the world, and none of the bounding plane
+    // intersections do.  Thus, if we don't find any of the edge intersection cases, we have to look for that last case.
+    GeoPoint[] edgePoints = findLargestSolution(minXZ, maxXZ, minYZ, maxYZ);
+      
+    if (edgePoints.length == 0) {
+      // If we still haven't encountered anything, we need to look at single-plane/world intersections.
+      // We detect these by looking at the world model and noting its x, y, and z bounds.
+
+      if (Z - worldMinZ >= -Vector.MINIMUM_RESOLUTION && Z - worldMaxZ <= Vector.MINIMUM_RESOLUTION &&
+        (minY - worldMinY < -Vector.MINIMUM_RESOLUTION) &&
+        (maxY - worldMaxY > Vector.MINIMUM_RESOLUTION) &&
+        (minX - worldMinX < -Vector.MINIMUM_RESOLUTION) &&
+        (maxX - worldMaxX > Vector.MINIMUM_RESOLUTION)) {
+        // Find any point on the minZ plane that intersects the world
+        // First construct a perpendicular plane that will allow us to find a sample point.
+        // This plane is vertical and goes through the points (0,0,0) and (1,0,0)
+        // Then use it to compute a sample point.
+        edgePoints = new GeoPoint[]{zPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane)};
+      }
+    }
+
+    this.edgePoints = edgePoints;
+  }
+
+  @Override
+  protected GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+  
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return minXPlane.isWithin(x, y, z) &&
+      maxXPlane.isWithin(x, y, z) &&
+      minYPlane.isWithin(x, y, z) &&
+      maxYPlane.isWithin(x, y, z) &&
+      zPlane.evaluateIsZero(x, y, z);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    
+    //System.err.println(this+" getrelationship with "+path);
+    final int insideRectangle = isShapeInsideArea(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some inside");
+      return OVERLAPS;
+    }
+
+    // Figure out if the entire XYZArea is contained by the shape.
+    final int insideShape = isAreaInsideShape(path);
+    if (insideShape == SOME_INSIDE) {
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
+      //System.err.println(" inside of each other");
+      return OVERLAPS;
+    }
+
+    if (path.intersects(zPlane, notableZPoints, minXPlane, maxXPlane, minYPlane, maxYPlane)) {
+      //System.err.println(" edges intersect");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      //System.err.println(" shape inside rectangle");
+      return WITHIN;
+    }
+
+    if (insideShape == ALL_INSIDE) {
+      //System.err.println(" shape contains rectangle");
+      return CONTAINS;
+    }
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof XYdZSolid))
+      return false;
+    XYdZSolid other = (XYdZSolid) o;
+    if (!super.equals(other)) {
+      return false;
+    }
+    return other.minXPlane.equals(minXPlane) &&
+      other.maxXPlane.equals(maxXPlane) &&
+      other.minYPlane.equals(minYPlane) &&
+      other.maxYPlane.equals(maxYPlane) &&
+      other.zPlane.equals(zPlane);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result  + minXPlane.hashCode();
+    result = 31 * result  + maxXPlane.hashCode();
+    result = 31 * result  + minYPlane.hashCode();
+    result = 31 * result  + maxYPlane.hashCode();
+    result = 31 * result  + zPlane.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "XYdZSolid: {planetmodel="+planetModel+", minXplane="+minXPlane+", maxXplane="+maxXPlane+", minYplane="+minYPlane+", maxYplane="+maxYPlane+", zplane="+zPlane+"}";
+  }
+  
+}
+  

Added: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XdYZSolid.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XdYZSolid.java?rev=1695700&view=auto
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XdYZSolid.java (added)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XdYZSolid.java Thu Aug 13 12:29:29 2015
@@ -0,0 +1,205 @@
+package org.apache.lucene.geo3d;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in Y
+ *
+ * @lucene.internal
+ */
+public class XdYZSolid extends BaseXYZSolid {
+
+  /** Min-X plane */
+  protected final SidedPlane minXPlane;
+  /** Max-X plane */
+  protected final SidedPlane maxXPlane;
+  /** Y plane */
+  protected final Plane yPlane;
+  /** Min-Z plane */
+  protected final SidedPlane minZPlane;
+  /** Max-Z plane */
+  protected final SidedPlane maxZPlane;
+  
+  /** These are the edge points of the shape, which are defined to be at least one point on
+   * each surface area boundary.  In the case of a solid, this includes points which represent
+   * the intersection of XYZ bounding planes and the planet, as well as points representing
+   * the intersection of single bounding planes with the planet itself.
+   */
+  protected final GeoPoint[] edgePoints;
+
+  /** Notable points for YPlane */
+  protected final GeoPoint[] notableYPoints;
+
+  /**
+   *@param planetModel is the planet model.
+   *@param minX is the minimum X value.
+   *@param maxX is the maximum X value.
+   *@param Y is the Y value.
+   *@param minZ is the minimum Z value.
+   *@param maxZ is the maximum Z value.
+   */
+  public XdYZSolid(final PlanetModel planetModel,
+    final double minX,
+    final double maxX,
+    final double Y,
+    final double minZ,
+    final double maxZ) {
+    super(planetModel);
+    // Argument checking
+    if (maxX - minX < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("X values in wrong order or identical");
+    if (maxZ - minZ < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("Z values in wrong order or identical");
+
+    final double worldMinX = planetModel.getMinimumXValue();
+    final double worldMaxX = planetModel.getMaximumXValue();
+    final double worldMinY = planetModel.getMinimumYValue();
+    final double worldMaxY = planetModel.getMaximumYValue();
+    final double worldMinZ = planetModel.getMinimumZValue();
+    final double worldMaxZ = planetModel.getMaximumZValue();
+    
+    // Construct the planes
+    minXPlane = new SidedPlane(maxX,0.0,0.0,xUnitVector,-minX);
+    maxXPlane = new SidedPlane(minX,0.0,0.0,xUnitVector,-maxX);
+    yPlane = new Plane(yUnitVector,-Y);
+    minZPlane = new SidedPlane(0.0,0.0,maxZ,zUnitVector,-minZ);
+    maxZPlane = new SidedPlane(0.0,0.0,minZ,zUnitVector,-maxZ);
+      
+    // We need at least one point on the planet surface for each manifestation of the shape.
+    // There can be up to 2 (on opposite sides of the world).  But we have to go through
+    // 4 combinations of adjacent planes in order to find out if any have 2 intersection solution.
+    // Typically, this requires 4 square root operations. 
+    final GeoPoint[] minXY = minXPlane.findIntersections(planetModel,yPlane,maxXPlane,minZPlane,maxZPlane);
+    final GeoPoint[] maxXY = maxXPlane.findIntersections(planetModel,yPlane,minXPlane,minZPlane,maxZPlane);
+    final GeoPoint[] YminZ = yPlane.findIntersections(planetModel,minZPlane,maxZPlane,minXPlane,maxXPlane);
+    final GeoPoint[] YmaxZ = yPlane.findIntersections(planetModel,maxZPlane,minZPlane,minXPlane,maxXPlane);
+      
+    notableYPoints = glueTogether(minXY, maxXY, YminZ, YmaxZ);
+
+    // Now, compute the edge points.
+    // This is the trickiest part of setting up an XYZSolid.  We've computed intersections already, so
+    // we'll start there.  We know that at most there will be two disconnected shapes on the planet surface.
+    // But there's also a case where exactly one plane slices through the world, and none of the bounding plane
+    // intersections do.  Thus, if we don't find any of the edge intersection cases, we have to look for that last case.
+    GeoPoint[] edgePoints = findLargestSolution(minXY, maxXY, YminZ, YmaxZ);
+      
+    if (edgePoints.length == 0) {
+      // If we still haven't encountered anything, we need to look at single-plane/world intersections.
+      // We detect these by looking at the world model and noting its x, y, and z bounds.
+
+      if (Y - worldMinY >= -Vector.MINIMUM_RESOLUTION && Y - worldMaxY <= Vector.MINIMUM_RESOLUTION &&
+        (minX - worldMinX < -Vector.MINIMUM_RESOLUTION) &&
+        (maxX - worldMaxX > Vector.MINIMUM_RESOLUTION) &&
+        (minZ - worldMinZ < -Vector.MINIMUM_RESOLUTION) &&
+        (maxZ - worldMaxZ > Vector.MINIMUM_RESOLUTION)) {
+        // Find any point on the minY plane that intersects the world
+        // First construct a perpendicular plane that will allow us to find a sample point.
+        // This plane is vertical and goes through the points (0,0,0) and (0,1,0)
+        // Then use it to compute a sample point.
+        edgePoints = new GeoPoint[]{yPlane.getSampleIntersectionPoint(planetModel, yVerticalPlane)};
+      }
+    }
+
+    this.edgePoints = edgePoints;
+  }
+
+  @Override
+  protected GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+  
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return minXPlane.isWithin(x, y, z) &&
+      maxXPlane.isWithin(x, y, z) &&
+      yPlane.evaluateIsZero(x, y, z) &&
+      minZPlane.isWithin(x, y, z) &&
+      maxZPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    //System.err.println(this+" getrelationship with "+path);
+    final int insideRectangle = isShapeInsideArea(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some inside");
+      return OVERLAPS;
+    }
+
+    // Figure out if the entire XYZArea is contained by the shape.
+    final int insideShape = isAreaInsideShape(path);
+    if (insideShape == SOME_INSIDE) {
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
+      //System.err.println(" inside of each other");
+      return OVERLAPS;
+    }
+
+    if (path.intersects(yPlane, notableYPoints, minXPlane, maxXPlane, minZPlane, maxZPlane)) {
+      //System.err.println(" edges intersect");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      //System.err.println(" shape inside rectangle");
+      return WITHIN;
+    }
+
+    if (insideShape == ALL_INSIDE) {
+      //System.err.println(" shape contains rectangle");
+      return CONTAINS;
+    }
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof XdYZSolid))
+      return false;
+    XdYZSolid other = (XdYZSolid) o;
+    if (!super.equals(other)) {
+      return false;
+    }
+    return other.minXPlane.equals(minXPlane) &&
+      other.maxXPlane.equals(maxXPlane) &&
+      other.yPlane.equals(yPlane) &&
+      other.minZPlane.equals(minZPlane) &&
+      other.maxZPlane.equals(maxZPlane);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result  + minXPlane.hashCode();
+    result = 31 * result  + maxXPlane.hashCode();
+    result = 31 * result  + yPlane.hashCode();
+    result = 31 * result  + minZPlane.hashCode();
+    result = 31 * result  + maxZPlane.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "XdYZSolid: {planetmodel="+planetModel+", minXplane="+minXPlane+", maxXplane="+maxXPlane+", yplane="+yPlane+", minZplane="+minZPlane+", maxZplane="+maxZPlane+"}";
+  }
+  
+}
+  

Added: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXYZSolid.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXYZSolid.java?rev=1695700&view=auto
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXYZSolid.java (added)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXYZSolid.java Thu Aug 13 12:29:29 2015
@@ -0,0 +1,207 @@
+package org.apache.lucene.geo3d;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in X.
+ *
+ * @lucene.internal
+ */
+public class dXYZSolid extends BaseXYZSolid {
+
+  /** X plane */
+  protected final Plane xPlane;
+  /** Min-Y plane */
+  protected final SidedPlane minYPlane;
+  /** Max-Y plane */
+  protected final SidedPlane maxYPlane;
+  /** Min-Z plane */
+  protected final SidedPlane minZPlane;
+  /** Max-Z plane */
+  protected final SidedPlane maxZPlane;
+  
+  /** These are the edge points of the shape, which are defined to be at least one point on
+   * each surface area boundary.  In the case of a solid, this includes points which represent
+   * the intersection of XYZ bounding planes and the planet, as well as points representing
+   * the intersection of single bounding planes with the planet itself.
+   */
+  protected final GeoPoint[] edgePoints;
+
+  /** Notable points for XPlane */
+  protected final GeoPoint[] notableXPoints;
+
+  /**
+   *@param planetModel is the planet model.
+   *@param X is the X value.
+   *@param minY is the minimum Y value.
+   *@param maxY is the maximum Y value.
+   *@param minZ is the minimum Z value.
+   *@param maxZ is the maximum Z value.
+   */
+  public dXYZSolid(final PlanetModel planetModel,
+    final double X,
+    final double minY,
+    final double maxY,
+    final double minZ,
+    final double maxZ) {
+    super(planetModel);
+    // Argument checking
+    if (maxY - minY < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("Y values in wrong order or identical");
+    if (maxZ - minZ < Vector.MINIMUM_RESOLUTION)
+      throw new IllegalArgumentException("Z values in wrong order or identical");
+
+    final double worldMinX = planetModel.getMinimumXValue();
+    final double worldMaxX = planetModel.getMaximumXValue();
+    final double worldMinY = planetModel.getMinimumYValue();
+    final double worldMaxY = planetModel.getMaximumYValue();
+    final double worldMinZ = planetModel.getMinimumZValue();
+    final double worldMaxZ = planetModel.getMaximumZValue();
+    
+    // Construct the planes
+    xPlane = new Plane(xUnitVector,-X);
+    minYPlane = new SidedPlane(0.0,maxY,0.0,yUnitVector,-minY);
+    maxYPlane = new SidedPlane(0.0,minY,0.0,yUnitVector,-maxY);
+    minZPlane = new SidedPlane(0.0,0.0,maxZ,zUnitVector,-minZ);
+    maxZPlane = new SidedPlane(0.0,0.0,minZ,zUnitVector,-maxZ);
+      
+    // We need at least one point on the planet surface for each manifestation of the shape.
+    // There can be up to 2 (on opposite sides of the world).  But we have to go through
+    // 4 combinations of adjacent planes in order to find out if any have 2 intersection solution.
+    // Typically, this requires 4 square root operations. 
+    final GeoPoint[] XminY = xPlane.findIntersections(planetModel,minYPlane,maxYPlane,minZPlane,maxZPlane);
+    final GeoPoint[] XmaxY = xPlane.findIntersections(planetModel,maxYPlane,minYPlane,minZPlane,maxZPlane);
+    final GeoPoint[] XminZ = xPlane.findIntersections(planetModel,minZPlane,maxZPlane,minYPlane,maxYPlane);
+    final GeoPoint[] XmaxZ = xPlane.findIntersections(planetModel,maxZPlane,minZPlane,minYPlane,maxYPlane);
+
+    notableXPoints = glueTogether(XminY, XmaxY, XminZ, XmaxZ);
+
+    // Now, compute the edge points.
+    // This is the trickiest part of setting up an XYZSolid.  We've computed intersections already, so
+    // we'll start there.  We know that at most there will be two disconnected shapes on the planet surface.
+    // But there's also a case where exactly one plane slices through the world, and none of the bounding plane
+    // intersections do.  Thus, if we don't find any of the edge intersection cases, we have to look for that last case.
+    GeoPoint[] edgePoints = findLargestSolution(XminY,XmaxY,XminZ,XmaxZ);
+      
+    if (edgePoints.length == 0) {
+      // If we still haven't encountered anything, we need to look at single-plane/world intersections.
+      // We detect these by looking at the world model and noting its x, y, and z bounds.
+      // For the single-dimension degenerate case, there's really only one plane that can possibly intersect the world.
+        
+      if (X - worldMinX >= -Vector.MINIMUM_RESOLUTION && X - worldMaxX <= Vector.MINIMUM_RESOLUTION &&
+        (minY - worldMinY < -Vector.MINIMUM_RESOLUTION) &&
+        (maxY - worldMaxY > Vector.MINIMUM_RESOLUTION) &&
+        (minZ - worldMinZ < -Vector.MINIMUM_RESOLUTION) &&
+        (maxZ - worldMaxZ > Vector.MINIMUM_RESOLUTION)) {
+        // Find any point on the X plane that intersects the world
+        // First construct a perpendicular plane that will allow us to find a sample point.
+        // This plane is vertical and goes through the points (0,0,0) and (1,0,0)
+        // Then use it to compute a sample point.
+        edgePoints = new GeoPoint[]{xPlane.getSampleIntersectionPoint(planetModel, xVerticalPlane)};
+      }
+    }
+
+    this.edgePoints = edgePoints;
+  }
+
+  @Override
+  protected GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+  
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    return xPlane.evaluateIsZero(x, y, z) &&
+      minYPlane.isWithin(x, y, z) &&
+      maxYPlane.isWithin(x, y, z) &&
+      minZPlane.isWithin(x, y, z) &&
+      maxZPlane.isWithin(x, y, z);
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    //System.err.println(this+" getrelationship with "+path);
+    final int insideRectangle = isShapeInsideArea(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some inside");
+      return OVERLAPS;
+    }
+
+    // Figure out if the entire XYZArea is contained by the shape.
+    final int insideShape = isAreaInsideShape(path);
+    if (insideShape == SOME_INSIDE) {
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
+      //System.err.println(" inside of each other");
+      return OVERLAPS;
+    }
+
+    // The entire locus of points in this shape is on a single plane, so we only need ot look for an intersection with that plane.
+    if (path.intersects(xPlane, notableXPoints, minYPlane, maxYPlane, minZPlane, maxZPlane)) {
+      //System.err.println(" edges intersect");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      //System.err.println(" shape inside rectangle");
+      return WITHIN;
+    }
+
+    if (insideShape == ALL_INSIDE) {
+      //System.err.println(" shape contains rectangle");
+      return CONTAINS;
+    }
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof dXYZSolid))
+      return false;
+    dXYZSolid other = (dXYZSolid) o;
+    if (!super.equals(other)) {
+      return false;
+    }
+    return other.xPlane.equals(xPlane) &&
+      other.minYPlane.equals(minYPlane) &&
+      other.maxYPlane.equals(maxYPlane) &&
+      other.minZPlane.equals(minZPlane) &&
+      other.maxZPlane.equals(maxZPlane);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result  + xPlane.hashCode();
+    result = 31 * result  + minYPlane.hashCode();
+    result = 31 * result  + maxYPlane.hashCode();
+    result = 31 * result  + minZPlane.hashCode();
+    result = 31 * result  + maxZPlane.hashCode();
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "dXYZSolid: {planetmodel="+planetModel+", xplane="+xPlane+", minYplane="+minYPlane+", maxYplane="+maxYPlane+", minZplane="+minZPlane+", maxZplane="+maxZPlane+"}";
+  }
+  
+}
+  

Added: lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXdYdZSolid.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXdYdZSolid.java?rev=1695700&view=auto
==============================================================================
--- lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXdYdZSolid.java (added)
+++ lucene/dev/branches/lucene6699/lucene/spatial3d/src/java/org/apache/lucene/geo3d/dXdYdZSolid.java Thu Aug 13 12:29:29 2015
@@ -0,0 +1,150 @@
+package org.apache.lucene.geo3d;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * 3D rectangle, bounded on six sides by X,Y,Z limits, degenerate in all dimensions
+ *
+ * @lucene.internal
+ */
+public class dXdYdZSolid extends BaseXYZSolid {
+
+  /** On surface? */
+  protected final boolean isOnSurface;
+  /** The point */
+  protected final GeoPoint thePoint;
+  
+  /** These are the edge points of the shape, which are defined to be at least one point on
+   * each surface area boundary.  In the case of a solid, this includes points which represent
+   * the intersection of XYZ bounding planes and the planet, as well as points representing
+   * the intersection of single bounding planes with the planet itself.
+   */
+  protected final GeoPoint[] edgePoints;
+
+  protected static final GeoPoint[] nullPoints = new GeoPoint[0];
+  
+  /**
+   *@param planetModel is the planet model.
+   *@param X is the X value.
+   *@param Y is the Y value.
+   *@param Z is the Z value.
+   */
+  public dXdYdZSolid(final PlanetModel planetModel,
+    final double X,
+    final double Y,
+    final double Z) {
+    super(planetModel);
+    isOnSurface = planetModel.pointOnSurface(X,Y,Z);
+    if (isOnSurface) {
+      thePoint = new GeoPoint(X,Y,Z);
+      edgePoints = new GeoPoint[]{thePoint};
+    } else {
+      thePoint = null;
+      edgePoints = nullPoints;
+    }
+  }
+
+  @Override
+  protected GeoPoint[] getEdgePoints() {
+    return edgePoints;
+  }
+  
+  @Override
+  public boolean isWithin(final double x, final double y, final double z) {
+    if (!isOnSurface) {
+      return false;
+    }
+    return Math.abs(thePoint.x - x) < Vector.MINIMUM_RESOLUTION &&
+      Math.abs(thePoint.y - y) < Vector.MINIMUM_RESOLUTION &&
+      Math.abs(thePoint.z - z) < Vector.MINIMUM_RESOLUTION;
+  }
+
+  @Override
+  public int getRelationship(final GeoShape path) {
+    if (!isOnSurface) {
+      return DISJOINT;
+    }
+    
+    //System.err.println(this+" getrelationship with "+path);
+    final int insideRectangle = isShapeInsideArea(path);
+    if (insideRectangle == SOME_INSIDE) {
+      //System.err.println(" some inside");
+      return OVERLAPS;
+    }
+
+    // Figure out if the entire XYZArea is contained by the shape.
+    final int insideShape = isAreaInsideShape(path);
+    if (insideShape == SOME_INSIDE) {
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE && insideShape == ALL_INSIDE) {
+      //System.err.println(" inside of each other");
+      return OVERLAPS;
+    }
+
+    if (path.isWithin(thePoint)) {
+      //System.err.println(" edges intersect");
+      return OVERLAPS;
+    }
+
+    if (insideRectangle == ALL_INSIDE) {
+      //System.err.println(" shape inside rectangle");
+      return WITHIN;
+    }
+
+    if (insideShape == ALL_INSIDE) {
+      //System.err.println(" shape contains rectangle");
+      return CONTAINS;
+    }
+    //System.err.println(" disjoint");
+    return DISJOINT;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof dXdYdZSolid))
+      return false;
+    dXdYdZSolid other = (dXdYdZSolid) o;
+    if (!super.equals(other) ||
+      other.isOnSurface != isOnSurface) {
+      return false;
+    }
+    if (isOnSurface) {
+      return other.thePoint.equals(thePoint);
+    }
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = super.hashCode();
+    result = 31 * result + (isOnSurface?1:0);
+    if (isOnSurface) {
+      result = 31 * result  + thePoint.hashCode();
+    }
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return "dXdYdZSolid: {planetmodel="+planetModel+", isOnSurface="+isOnSurface+", thePoint="+thePoint+"}";
+  }
+  
+}
+