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/09/02 21:59:32 UTC
svn commit: r1700883 [3/5] - in /lucene/dev/trunk/lucene: ./
sandbox/src/java/org/apache/lucene/bkdtree/
sandbox/src/java/org/apache/lucene/rangetree/
spatial/src/java/org/apache/lucene/spatial/spatial4j/
spatial/src/test/org/apache/lucene/spatial/spat...
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLatitudeZone.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLatitudeZone.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLatitudeZone.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLatitudeZone.java Wed Sep 2 19:59:31 2015
@@ -86,21 +86,11 @@ public class GeoDegenerateLatitudeZone e
return p.intersects(planetModel, plane, notablePoints, planePoints, bounds);
}
- /**
- * Compute longitude/latitude bounds for the shape.
- *
- * @param bounds is the optional input bounds object. If this is null,
- * a bounds object will be created. Otherwise, the input object will be modified.
- * @return a Bounds object describing the shape's bounds. If the bounds cannot
- * be computed, then return a Bounds object with noLongitudeBound,
- * noTopLatitudeBound, and noBottomLatitudeBound.
- */
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.noLongitudeBound().addLatitudeZone(latitude);
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ bounds.noLongitudeBound()
+ .addHorizontalPlane(planetModel, latitude, plane);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLongitudeSlice.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLongitudeSlice.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLongitudeSlice.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateLongitudeSlice.java Wed Sep 2 19:59:31 2015
@@ -98,12 +98,11 @@ public class GeoDegenerateLongitudeSlice
}
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.noTopLatitudeBound().noBottomLatitudeBound();
- bounds.addLongitudeSlice(longitude, longitude);
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ bounds
+ .addVerticalPlane(planetModel, longitude, plane, boundingPlane)
+ .addPoint(planetModel.NORTH_POLE).addPoint(planetModel.SOUTH_POLE);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegeneratePoint.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegeneratePoint.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegeneratePoint.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegeneratePoint.java Wed Sep 2 19:59:31 2015
@@ -74,11 +74,8 @@ public class GeoDegeneratePoint extends
}
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.addPoint(latitude, longitude);
- return bounds;
+ public void getBounds(Bounds bounds) {
+ bounds.addPoint(this);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateVerticalLine.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateVerticalLine.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateVerticalLine.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoDegenerateVerticalLine.java Wed Sep 2 19:59:31 2015
@@ -77,8 +77,8 @@ public class GeoDegenerateVerticalLine e
final double cosLongitude = Math.cos(longitude);
// Now build the two points
- this.UHC = new GeoPoint(planetModel, sinTopLat, sinLongitude, cosTopLat, cosLongitude);
- this.LHC = new GeoPoint(planetModel, sinBottomLat, sinLongitude, cosBottomLat, cosLongitude);
+ this.UHC = new GeoPoint(planetModel, sinTopLat, sinLongitude, cosTopLat, cosLongitude, topLat, longitude);
+ this.LHC = new GeoPoint(planetModel, sinBottomLat, sinLongitude, cosBottomLat, cosLongitude, bottomLat, longitude);
this.plane = new Plane(cosLongitude, sinLongitude);
@@ -146,12 +146,10 @@ public class GeoDegenerateVerticalLine e
}
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.addLatitudeZone(topLat).addLatitudeZone(bottomLat)
- .addLongitudeSlice(longitude, longitude);
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ bounds.addVerticalPlane(planetModel, longitude, plane, boundingPlane, topPlane, bottomPlane)
+ .addPoint(UHC).addPoint(LHC);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLatitudeZone.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLatitudeZone.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLatitudeZone.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLatitudeZone.java Wed Sep 2 19:59:31 2015
@@ -121,11 +121,11 @@ public class GeoLatitudeZone extends Geo
}
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.noLongitudeBound().addLatitudeZone(topLat).addLatitudeZone(bottomLat);
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ bounds.noLongitudeBound()
+ .addHorizontalPlane(planetModel, topLat, topPlane)
+ .addHorizontalPlane(planetModel, bottomLat, bottomPlane);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLongitudeSlice.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLongitudeSlice.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLongitudeSlice.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoLongitudeSlice.java Wed Sep 2 19:59:31 2015
@@ -129,12 +129,13 @@ public class GeoLongitudeSlice extends G
}
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.noTopLatitudeBound().noBottomLatitudeBound();
- bounds.addLongitudeSlice(leftLon, rightLon);
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ bounds
+ .addVerticalPlane(planetModel, leftLon, leftPlane, rightPlane)
+ .addVerticalPlane(planetModel, rightLon, rightPlane, leftPlane)
+ .addPoint(planetModel.NORTH_POLE)
+ .addPoint(planetModel.SOUTH_POLE);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthLatitudeZone.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthLatitudeZone.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthLatitudeZone.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthLatitudeZone.java Wed Sep 2 19:59:31 2015
@@ -100,11 +100,10 @@ public class GeoNorthLatitudeZone extend
}
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.noLongitudeBound().noTopLatitudeBound().addLatitudeZone(bottomLat);
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ bounds
+ .addHorizontalPlane(planetModel, bottomLat, bottomPlane);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthRectangle.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthRectangle.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoNorthRectangle.java Wed Sep 2 19:59:31 2015
@@ -90,8 +90,8 @@ public class GeoNorthRectangle extends G
final double cosRightLon = Math.cos(rightLon);
// Now build the points
- this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
- this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
+ this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon, bottomLat, rightLon);
+ this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon, bottomLat, leftLon);
final double middleLat = (Math.PI * 0.5 + bottomLat) * 0.5;
final double sinMiddleLat = Math.sin(middleLat);
@@ -176,12 +176,13 @@ public class GeoNorthRectangle extends G
}
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.noTopLatitudeBound().addLatitudeZone(bottomLat)
- .addLongitudeSlice(leftLon, rightLon);
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ bounds
+ .addHorizontalPlane(planetModel, bottomLat, bottomPlane, leftPlane, rightPlane)
+ .addVerticalPlane(planetModel, leftLon, leftPlane, bottomPlane, rightPlane)
+ .addVerticalPlane(planetModel, rightLon, rightPlane, bottomPlane, leftPlane)
+ .addPoint(LLHC).addPoint(LRHC).addPoint(planetModel.NORTH_POLE);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPath.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPath.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPath.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPath.java Wed Sep 2 19:59:31 2015
@@ -140,10 +140,14 @@ public class GeoPath extends GeoBaseDist
}
final GeoPoint upperPoint = new GeoPoint(planetModel, upperLat, upperLon);
final GeoPoint lowerPoint = new GeoPoint(planetModel, lowerLat, lowerLon);
+ final GeoPoint point = points.get(0);
+
+ // Construct normal plane
+ final Plane normalPlane = Plane.constructNormalizedZPlane(upperPoint, lowerPoint, point);
- final SegmentEndpoint onlyEndpoint = new SegmentEndpoint(points.get(0), upperPoint, lowerPoint);
+ final SegmentEndpoint onlyEndpoint = new SegmentEndpoint(point, normalPlane, upperPoint, lowerPoint);
endPoints.add(onlyEndpoint);
- this.edgePoints = new GeoPoint[]{upperPoint};
+ this.edgePoints = new GeoPoint[]{onlyEndpoint.circlePlane.getSampleIntersectionPoint(planetModel, normalPlane)};
return;
}
@@ -278,8 +282,8 @@ public class GeoPath extends GeoBaseDist
}
@Override
- public Bounds getBounds(Bounds bounds) {
- bounds = super.getBounds(bounds);
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
// For building bounds, order matters. We want to traverse
// never more than 180 degrees longitude at a pop or we risk having the
// bounds object get itself inverted. So do the edges first.
@@ -289,7 +293,6 @@ public class GeoPath extends GeoBaseDist
for (SegmentEndpoint pathPoint : endPoints) {
pathPoint.getBounds(planetModel, bounds);
}
- return bounds;
}
@Override
@@ -339,7 +342,9 @@ public class GeoPath extends GeoBaseDist
public final GeoPoint[] notablePoints;
/** No notable points from the circle itself */
public final static GeoPoint[] circlePoints = new GeoPoint[0];
-
+ /** Null membership */
+ public final static Membership[] NO_MEMBERSHIP = new Membership[0];
+
/** Base case. Does nothing at all.
*/
public SegmentEndpoint(final GeoPoint point) {
@@ -355,14 +360,12 @@ public class GeoPath extends GeoBaseDist
*@param upperPoint is a point that must be on the circle plane.
*@param lowerPoint is another point that must be on the circle plane.
*/
- public SegmentEndpoint(final GeoPoint point, final GeoPoint upperPoint, final GeoPoint lowerPoint) {
+ public SegmentEndpoint(final GeoPoint point, final Plane normalPlane, final GeoPoint upperPoint, final GeoPoint lowerPoint) {
this.point = point;
- // Construct normal plane
- final Plane normalPlane = Plane.constructNormalizedVerticalPlane(upperPoint, lowerPoint, point);
// Construct a sided plane that goes through the two points and whose normal is in the normalPlane.
this.circlePlane = SidedPlane.constructNormalizedPerpendicularSidedPlane(point, normalPlane, upperPoint, lowerPoint);
- this.cutoffPlanes = new Membership[0];
- this.notablePoints = new GeoPoint[0];
+ this.cutoffPlanes = NO_MEMBERSHIP;
+ this.notablePoints = circlePoints;
}
/** Constructor for case (2).
@@ -533,7 +536,7 @@ public class GeoPath extends GeoBaseDist
bounds.addPoint(point);
if (circlePlane == null)
return;
- circlePlane.recordBounds(planetModel, bounds);
+ bounds.addPlane(planetModel, circlePlane);
}
@Override
@@ -769,15 +772,11 @@ public class GeoPath extends GeoBaseDist
*/
public void getBounds(final PlanetModel planetModel, Bounds bounds) {
// We need to do all bounding planes as well as corner points
- bounds.addPoint(start).addPoint(end);
- upperConnectingPlane.recordBounds(planetModel, startCutoffPlane, bounds, lowerConnectingPlane, endCutoffPlane);
- startCutoffPlane.recordBounds(planetModel, lowerConnectingPlane, bounds, endCutoffPlane, upperConnectingPlane);
- lowerConnectingPlane.recordBounds(planetModel, endCutoffPlane, bounds, upperConnectingPlane, startCutoffPlane);
- endCutoffPlane.recordBounds(planetModel, upperConnectingPlane, bounds, startCutoffPlane, lowerConnectingPlane);
- upperConnectingPlane.recordBounds(planetModel, bounds, lowerConnectingPlane, startCutoffPlane, endCutoffPlane);
- lowerConnectingPlane.recordBounds(planetModel, bounds, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
- startCutoffPlane.recordBounds(planetModel, bounds, endCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
- endCutoffPlane.recordBounds(planetModel, bounds, startCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
+ bounds.addPoint(start).addPoint(end).addPoint(ULHC).addPoint(URHC).addPoint(LRHC).addPoint(LLHC);
+ bounds.addPlane(planetModel, upperConnectingPlane, lowerConnectingPlane, startCutoffPlane, endCutoffPlane);
+ bounds.addPlane(planetModel, lowerConnectingPlane, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
+ bounds.addPlane(planetModel, startCutoffPlane, endCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
+ bounds.addPlane(planetModel, endCutoffPlane, startCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
}
}
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPoint.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPoint.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPoint.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoPoint.java Wed Sep 2 19:59:31 2015
@@ -85,10 +85,12 @@ public class GeoPoint extends Vector {
public GeoPoint(final double magnitude, final double x, final double y, final double z, double lat, double lon) {
super(x * magnitude, y * magnitude, z * magnitude);
this.magnitude = magnitude;
- if (lat > Math.PI * 0.5 || lat < -Math.PI * 0.5)
- throw new IllegalArgumentException("Latitude out of range");
- if (lon < -Math.PI || lon > Math.PI)
- throw new IllegalArgumentException("Longitude out of range");
+ if (lat > Math.PI * 0.5 || lat < -Math.PI * 0.5) {
+ throw new IllegalArgumentException("Latitude " + lat + " is out of range: must range from -Math.PI/2 to Math.PI/2");
+ }
+ if (lon < -Math.PI || lon > Math.PI) {
+ throw new IllegalArgumentException("Longitude " + lon + " is out of range: must range from -Math.PI to Math.PI");
+ }
this.latitude = lat;
this.longitude = lon;
}
@@ -169,4 +171,24 @@ public class GeoPoint extends Vector {
}
return mag;
}
+
+ /** Compute whether point matches another.
+ *@param x is the x value
+ *@param y is the y value
+ *@param z is the z value
+ *@return true if the same.
+ */
+ public boolean isIdentical(final double x, final double y, final double z) {
+ return Math.abs(this.x - x) < MINIMUM_RESOLUTION &&
+ Math.abs(this.y - y) < MINIMUM_RESOLUTION &&
+ Math.abs(this.z - z) < MINIMUM_RESOLUTION;
+ }
+
+ @Override
+ public String toString() {
+ if (this.longitude == Double.NEGATIVE_INFINITY) {
+ return super.toString();
+ }
+ return "[lat="+getLatitude()+", lon="+getLongitude()+"]";
+ }
}
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoRectangle.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoRectangle.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoRectangle.java Wed Sep 2 19:59:31 2015
@@ -112,10 +112,10 @@ public class GeoRectangle extends GeoBas
final double cosRightLon = Math.cos(rightLon);
// Now build the four points
- this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
- this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon);
- this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
- this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
+ this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon, topLat, leftLon);
+ this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon, topLat, rightLon);
+ this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon, bottomLat, rightLon);
+ this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon, bottomLat, leftLon);
final double middleLat = (topLat + bottomLat) * 0.5;
final double sinMiddleLat = Math.sin(middleLat);
@@ -198,12 +198,13 @@ public class GeoRectangle extends GeoBas
}
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.addLatitudeZone(topLat).addLatitudeZone(bottomLat)
- .addLongitudeSlice(leftLon, rightLon);
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ bounds.addHorizontalPlane(planetModel, topLat, topPlane, bottomPlane, leftPlane, rightPlane)
+ .addVerticalPlane(planetModel, rightLon, rightPlane, topPlane, bottomPlane, leftPlane)
+ .addHorizontalPlane(planetModel, bottomLat, bottomPlane, topPlane, leftPlane, rightPlane)
+ .addVerticalPlane(planetModel, leftLon, leftPlane, topPlane, bottomPlane, rightPlane)
+ .addPoint(ULHC).addPoint(URHC).addPoint(LLHC).addPoint(LRHC);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoShape.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoShape.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoShape.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoShape.java Wed Sep 2 19:59:31 2015
@@ -54,14 +54,11 @@ public interface GeoShape extends Member
public boolean intersects(final Plane plane, final GeoPoint[] notablePoints, final Membership... bounds);
/**
- * Compute longitude/latitude bounds for the shape.
+ * Compute bounds for the shape.
*
- * @param bounds is the optional input bounds object. If this is null,
- * a bounds object will be created. Otherwise, the input object will be modified.
- * @return a Bounds object describing the shape's bounds. If the bounds cannot
- * be computed, then return a Bounds object with noLongitudeBound,
- * noTopLatitudeBound, and noBottomLatitudeBound.
+ * @param bounds is the input bounds object.
+ * The input object will be modified.
*/
- public Bounds getBounds(final Bounds bounds);
+ public void getBounds(final Bounds bounds);
}
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthLatitudeZone.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthLatitudeZone.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthLatitudeZone.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthLatitudeZone.java Wed Sep 2 19:59:31 2015
@@ -102,21 +102,11 @@ public class GeoSouthLatitudeZone extend
return p.intersects(planetModel, topPlane, notablePoints, planePoints, bounds);
}
- /**
- * Compute longitude/latitude bounds for the shape.
- *
- * @param bounds is the optional input bounds object. If this is null,
- * a bounds object will be created. Otherwise, the input object will be modified.
- * @return a Bounds object describing the shape's bounds. If the bounds cannot
- * be computed, then return a Bounds object with noLongitudeBound,
- * noTopLatitudeBound, and noBottomLatitudeBound.
- */
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.noLongitudeBound().addLatitudeZone(topLat).noBottomLatitudeBound();
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ bounds
+ .addHorizontalPlane(planetModel, topLat, topPlane);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthRectangle.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthRectangle.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoSouthRectangle.java Wed Sep 2 19:59:31 2015
@@ -94,8 +94,8 @@ public class GeoSouthRectangle extends G
final double cosRightLon = Math.cos(rightLon);
// Now build the four points
- this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
- this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon);
+ this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon, topLat, leftLon);
+ this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon, topLat, rightLon);
final double middleLat = (topLat - Math.PI * 0.5) * 0.5;
final double sinMiddleLat = Math.sin(middleLat);
@@ -174,12 +174,13 @@ public class GeoSouthRectangle extends G
}
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.addLatitudeZone(topLat).noBottomLatitudeBound()
- .addLongitudeSlice(leftLon, rightLon);
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ bounds
+ .addHorizontalPlane(planetModel, topLat, topPlane, leftPlane, rightPlane)
+ .addVerticalPlane(planetModel, leftLon, leftPlane, topPlane, rightPlane)
+ .addVerticalPlane(planetModel, rightLon, rightPlane, topPlane, leftPlane)
+ .addPoint(URHC).addPoint(ULHC).addPoint(planetModel.SOUTH_POLE);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideDegenerateHorizontalLine.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideDegenerateHorizontalLine.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideDegenerateHorizontalLine.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideDegenerateHorizontalLine.java Wed Sep 2 19:59:31 2015
@@ -90,8 +90,8 @@ public class GeoWideDegenerateHorizontal
final double cosRightLon = Math.cos(rightLon);
// Now build the two points
- this.LHC = new GeoPoint(planetModel, sinLatitude, sinLeftLon, cosLatitude, cosLeftLon);
- this.RHC = new GeoPoint(planetModel, sinLatitude, sinRightLon, cosLatitude, cosRightLon);
+ this.LHC = new GeoPoint(planetModel, sinLatitude, sinLeftLon, cosLatitude, cosLeftLon, latitude, leftLon);
+ this.RHC = new GeoPoint(planetModel, sinLatitude, sinRightLon, cosLatitude, cosRightLon, latitude, rightLon);
this.plane = new Plane(planetModel, sinLatitude);
@@ -167,12 +167,12 @@ public class GeoWideDegenerateHorizontal
}
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.addLatitudeZone(latitude)
- .addLongitudeSlice(leftLon, rightLon);
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ bounds.isWide()
+ .addHorizontalPlane(planetModel, latitude, plane, eitherBound)
+ .addPoint(LHC)
+ .addPoint(RHC);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideLongitudeSlice.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideLongitudeSlice.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideLongitudeSlice.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideLongitudeSlice.java Wed Sep 2 19:59:31 2015
@@ -135,12 +135,13 @@ public class GeoWideLongitudeSlice exten
}
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.noTopLatitudeBound().noBottomLatitudeBound();
- bounds.addLongitudeSlice(leftLon, rightLon);
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ bounds.isWide()
+ .addVerticalPlane(planetModel, leftLon, leftPlane)
+ .addVerticalPlane(planetModel, rightLon, rightPlane)
+ .addPoint(planetModel.NORTH_POLE)
+ .addPoint(planetModel.SOUTH_POLE);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideNorthRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideNorthRectangle.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideNorthRectangle.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideNorthRectangle.java Wed Sep 2 19:59:31 2015
@@ -94,8 +94,8 @@ public class GeoWideNorthRectangle exten
final double cosRightLon = Math.cos(rightLon);
// Now build the four points
- this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
- this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
+ this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon, bottomLat, rightLon);
+ this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon, bottomLat, leftLon);
final double middleLat = (Math.PI * 0.5 + bottomLat) * 0.5;
final double sinMiddleLat = Math.sin(middleLat);
@@ -178,12 +178,13 @@ public class GeoWideNorthRectangle exten
}
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.noTopLatitudeBound().addLatitudeZone(bottomLat)
- .addLongitudeSlice(leftLon, rightLon);
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ bounds.isWide()
+ .addHorizontalPlane(planetModel, bottomLat, bottomPlane, eitherBound)
+ .addVerticalPlane(planetModel, leftLon, leftPlane, bottomPlane)
+ .addVerticalPlane(planetModel, rightLon, rightPlane, bottomPlane)
+ .addPoint(LLHC).addPoint(LRHC).addPoint(planetModel.NORTH_POLE);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideRectangle.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideRectangle.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideRectangle.java Wed Sep 2 19:59:31 2015
@@ -111,10 +111,10 @@ public class GeoWideRectangle extends Ge
final double cosRightLon = Math.cos(rightLon);
// Now build the four points
- this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
- this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon);
- this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
- this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
+ this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon, topLat, leftLon);
+ this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon, topLat, rightLon);
+ this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon, bottomLat, rightLon);
+ this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon, bottomLat, leftLon);
final double middleLat = (topLat + bottomLat) * 0.5;
final double sinMiddleLat = Math.sin(middleLat);
@@ -206,12 +206,14 @@ public class GeoWideRectangle extends Ge
}
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.addLatitudeZone(topLat).addLatitudeZone(bottomLat)
- .addLongitudeSlice(leftLon, rightLon);
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ bounds.isWide()
+ .addHorizontalPlane(planetModel, topLat, topPlane, bottomPlane, eitherBound)
+ .addVerticalPlane(planetModel, rightLon, rightPlane, topPlane, bottomPlane)
+ .addHorizontalPlane(planetModel, bottomLat, bottomPlane, topPlane, eitherBound)
+ .addVerticalPlane(planetModel, leftLon, leftPlane, topPlane, bottomPlane)
+ .addPoint(ULHC).addPoint(URHC).addPoint(LRHC).addPoint(LLHC);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideSouthRectangle.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideSouthRectangle.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideSouthRectangle.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWideSouthRectangle.java Wed Sep 2 19:59:31 2015
@@ -94,8 +94,8 @@ public class GeoWideSouthRectangle exten
final double cosRightLon = Math.cos(rightLon);
// Now build the four points
- this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
- this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon);
+ this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon, topLat, leftLon);
+ this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon, topLat, rightLon);
final double middleLat = (topLat - Math.PI * 0.5) * 0.5;
final double sinMiddleLat = Math.sin(middleLat);
@@ -177,12 +177,13 @@ public class GeoWideSouthRectangle exten
}
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.addLatitudeZone(topLat).noBottomLatitudeBound()
- .addLongitudeSlice(leftLon, rightLon);
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ bounds.isWide()
+ .addHorizontalPlane(planetModel, topLat, topPlane, eitherBound)
+ .addVerticalPlane(planetModel, rightLon, rightPlane, topPlane)
+ .addVerticalPlane(planetModel, leftLon, leftPlane, topPlane)
+ .addPoint(ULHC).addPoint(URHC).addPoint(planetModel.SOUTH_POLE);
}
@Override
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWorld.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWorld.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWorld.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/GeoWorld.java Wed Sep 2 19:59:31 2015
@@ -68,11 +68,10 @@ public class GeoWorld extends GeoBaseBBo
}
@Override
- public Bounds getBounds(Bounds bounds) {
- if (bounds == null)
- bounds = new Bounds();
- bounds.noLongitudeBound().noTopLatitudeBound().noBottomLatitudeBound();
- return bounds;
+ public void getBounds(Bounds bounds) {
+ super.getBounds(bounds);
+ // Unnecessary
+ //bounds.noLongitudeBound().noTopLatitudeBound().noBottomLatitudeBound();
}
@Override
Added: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LatLonBounds.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LatLonBounds.java?rev=1700883&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LatLonBounds.java (added)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/LatLonBounds.java Wed Sep 2 19:59:31 2015
@@ -0,0 +1,323 @@
+package org.apache.lucene.geo3d;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * An object for accumulating latitude/longitude bounds information.
+ *
+ * @lucene.experimental
+ */
+public class LatLonBounds implements Bounds {
+
+ /** Set to true if no longitude bounds can be stated */
+ protected boolean noLongitudeBound = false;
+ /** Set to true if no top latitude bound can be stated */
+ protected boolean noTopLatitudeBound = false;
+ /** Set to true if no bottom latitude bound can be stated */
+ protected boolean noBottomLatitudeBound = false;
+
+ /** If non-null, the minimum latitude bound */
+ protected Double minLatitude = null;
+ /** If non-null, the maximum latitude bound */
+ protected Double maxLatitude = null;
+
+ // For longitude bounds, this class needs to worry about keeping track of the distinction
+ // between left-side bounds and right-side bounds. Points are always submitted in pairs
+ // which have a maximum longitude separation of Math.PI. It's therefore always possible
+ // to determine which point represents a left bound, and which point represents a right
+ // bound.
+ //
+ // The next problem is how to compare two of the same kind of bound, e.g. two left bounds.
+ // We need to keep track of the leftmost longitude of the shape, but since this is a circle,
+ // this is arbitrary. What we could try to do instead would be to find a pair of (left,right) bounds such
+ // that:
+ // (1) all other bounds are within, and
+ // (2) the left minus right distance is minimized
+ // Unfortunately, there are still shapes that cannot be summarized in this way correctly.
+ // For example. consider a spiral that entirely circles the globe; we might arbitrarily choose
+ // lat/lon bounds that do not in fact circle the globe.
+ //
+ // One way to handle the longitude issue correctly is therefore to stipulate that we
+ // walk the bounds of the shape in some kind of connected order. Each point or circle is therefore
+ // added in a sequence. We also need an interior point to make sure we have the right
+ // choice of longitude bounds. But even with this, we still can't always choose whether the actual shape
+ // goes right or left.
+ //
+ // We can make the specification truly general by submitting the following in order:
+ // addSide(PlaneSide side, Membership... constraints)
+ // ...
+ // This is unambiguous, but I still can't see yet how this would help compute the bounds. The plane
+ // solution would in general seem to boil down to the same logic that relies on points along the path
+ // to define the shape boundaries. I guess the one thing that you do know for a bounded edge is that
+ // the endpoints are actually connected. But it is not clear whether relationship helps in any way.
+ //
+ // In any case, if we specify shapes by a sequence of planes, we should stipulate that multiple sequences
+ // are allowed, provided they progressively tile an area of the sphere that is connected and sequential.
+ // For example, paths do alternating rectangles and circles, in sequence. Each sequence member is
+ // described by a sequence of planes. I think it would also be reasonable to insist that the first segment
+ // of a shape overlap or adjoin the previous shape.
+ //
+ // Here's a way to think about it that might help: Traversing every edge should grow the longitude bounds
+ // in the direction of the traversal. So if the traversal is always known to be less than PI in total longitude
+ // angle, then it is possible to use the endpoints to determine the unambiguous extension of the envelope.
+ // For example, say you are currently at longitude -0.5. The next point is at longitude PI-0.1. You could say
+ // that the difference in longitude going one way around would be beter than the distance the other way
+ // around, and therefore the longitude envelope should be extended accordingly. But in practice, when an
+ // edge goes near a pole and may be inclined as well, the longer longitude change might be the right path, even
+ // if the arc length is short. So this too doesn't work.
+ //
+ // Given we have a hard time making an exact match, here's the current proposal. The proposal is a
+ // heuristic, based on the idea that most areas are small compared to the circumference of the globe.
+ // We keep track of the last point we saw, and take each point as it arrives, and compute its longitude.
+ // Then, we have a choice as to which way to expand the envelope: we can expand by going to the left or
+ // to the right. We choose the direction with the least longitude difference. (If we aren't sure,
+ // and can recognize that, we can set "unconstrained in longitude".)
+
+ /** If non-null, the left longitude bound */
+ protected Double leftLongitude = null;
+ /** If non-null, the right longitude bound */
+ protected Double rightLongitude = null;
+
+ /** Construct an empty bounds object */
+ public LatLonBounds() {
+ }
+
+ // Accessor methods
+
+ /** Get maximum latitude, if any.
+ *@return maximum latitude or null.
+ */
+ public Double getMaxLatitude() {
+ return maxLatitude;
+ }
+
+ /** Get minimum latitude, if any.
+ *@return minimum latitude or null.
+ */
+ public Double getMinLatitude() {
+ return minLatitude;
+ }
+
+ /** Get left longitude, if any.
+ *@return left longitude, or null.
+ */
+ public Double getLeftLongitude() {
+ return leftLongitude;
+ }
+
+ /** Get right longitude, if any.
+ *@return right longitude, or null.
+ */
+ public Double getRightLongitude() {
+ return rightLongitude;
+ }
+
+ // Degenerate case check
+
+ /** Check if there's no longitude bound.
+ *@return true if no longitude bound.
+ */
+ public boolean checkNoLongitudeBound() {
+ return noLongitudeBound;
+ }
+
+ /** Check if there's no top latitude bound.
+ *@return true if no top latitude bound.
+ */
+ public boolean checkNoTopLatitudeBound() {
+ return noTopLatitudeBound;
+ }
+
+ /** Check if there's no bottom latitude bound.
+ *@return true if no bottom latitude bound.
+ */
+ public boolean checkNoBottomLatitudeBound() {
+ return noBottomLatitudeBound;
+ }
+
+ // Modification methods
+
+ @Override
+ public Bounds addPlane(final PlanetModel planetModel, final Plane plane, final Membership... bounds) {
+ plane.recordBounds(planetModel, this, bounds);
+ return this;
+ }
+
+ @Override
+ public Bounds addHorizontalPlane(final PlanetModel planetModel,
+ final double latitude,
+ final Plane horizontalPlane,
+ final Membership... bounds) {
+ if (!noTopLatitudeBound || !noBottomLatitudeBound) {
+ addLatitudeBound(latitude);
+ }
+ return this;
+ }
+
+ @Override
+ public Bounds addVerticalPlane(final PlanetModel planetModel,
+ final double longitude,
+ final Plane verticalPlane,
+ final Membership... bounds) {
+ if (!noLongitudeBound) {
+ addLongitudeBound(longitude);
+ }
+ return this;
+ }
+
+ @Override
+ public Bounds isWide() {
+ return noLongitudeBound();
+ }
+
+ @Override
+ public Bounds addXValue(final GeoPoint point) {
+ if (!noLongitudeBound) {
+ // Get a longitude value
+ addLongitudeBound(point.getLongitude());
+ }
+ return this;
+ }
+
+ @Override
+ public Bounds addYValue(final GeoPoint point) {
+ if (!noLongitudeBound) {
+ // Get a longitude value
+ addLongitudeBound(point.getLongitude());
+ }
+ return this;
+ }
+
+ @Override
+ public Bounds addZValue(final GeoPoint point) {
+ if (!noTopLatitudeBound || !noBottomLatitudeBound) {
+ // Compute a latitude value
+ double latitude = point.getLatitude();
+ addLatitudeBound(latitude);
+ }
+ return this;
+ }
+
+ @Override
+ public Bounds addPoint(GeoPoint point) {
+ if (!noLongitudeBound) {
+ // Get a longitude value
+ addLongitudeBound(point.getLongitude());
+ }
+ if (!noTopLatitudeBound || !noBottomLatitudeBound) {
+ // Compute a latitude value
+ addLatitudeBound(point.getLatitude());
+ }
+ return this;
+ }
+
+ @Override
+ public Bounds noLongitudeBound() {
+ noLongitudeBound = true;
+ leftLongitude = null;
+ rightLongitude = null;
+ return this;
+ }
+
+ @Override
+ public Bounds noTopLatitudeBound() {
+ noTopLatitudeBound = true;
+ maxLatitude = null;
+ return this;
+ }
+
+ @Override
+ public Bounds noBottomLatitudeBound() {
+ noBottomLatitudeBound = true;
+ minLatitude = null;
+ return this;
+ }
+
+ // Protected methods
+
+ /** Update latitude bound.
+ *@param latitude is the latitude.
+ */
+ protected void addLatitudeBound(double latitude) {
+ if (!noTopLatitudeBound && (maxLatitude == null || latitude > maxLatitude))
+ maxLatitude = latitude;
+ if (!noBottomLatitudeBound && (minLatitude == null || latitude < minLatitude))
+ minLatitude = latitude;
+ }
+
+ /** Update longitude bound.
+ *@param longitude is the new longitude value.
+ */
+ protected void addLongitudeBound(double longitude) {
+ // If this point is within the current bounds, we're done; otherwise
+ // expand one side or the other.
+ if (leftLongitude == null && rightLongitude == null) {
+ leftLongitude = longitude;
+ rightLongitude = longitude;
+ } else {
+ // Compute whether we're to the right of the left value. But the left value may be greater than
+ // the right value.
+ double currentLeftLongitude = leftLongitude;
+ double currentRightLongitude = rightLongitude;
+ if (currentRightLongitude < currentLeftLongitude)
+ currentRightLongitude += 2.0 * Math.PI;
+ // We have a range to look at that's going in the right way.
+ // Now, do the same trick with the computed longitude.
+ if (longitude < currentLeftLongitude)
+ longitude += 2.0 * Math.PI;
+
+ if (longitude < currentLeftLongitude || longitude > currentRightLongitude) {
+ // Outside of current bounds. Consider carefully how we'll expand.
+ double leftExtensionAmt;
+ double rightExtensionAmt;
+ if (longitude < currentLeftLongitude) {
+ leftExtensionAmt = currentLeftLongitude - longitude;
+ } else {
+ leftExtensionAmt = currentLeftLongitude + 2.0 * Math.PI - longitude;
+ }
+ if (longitude > currentRightLongitude) {
+ rightExtensionAmt = longitude - currentRightLongitude;
+ } else {
+ rightExtensionAmt = longitude + 2.0 * Math.PI - currentRightLongitude;
+ }
+ if (leftExtensionAmt < rightExtensionAmt) {
+ currentLeftLongitude = leftLongitude - leftExtensionAmt;
+ while (currentLeftLongitude <= -Math.PI) {
+ currentLeftLongitude += 2.0 * Math.PI;
+ }
+ leftLongitude = currentLeftLongitude;
+ } else {
+ currentRightLongitude = rightLongitude + rightExtensionAmt;
+ while (currentRightLongitude > Math.PI) {
+ currentRightLongitude -= 2.0 * Math.PI;
+ }
+ rightLongitude = currentRightLongitude;
+ }
+ }
+ }
+ double testRightLongitude = rightLongitude;
+ if (testRightLongitude < leftLongitude)
+ testRightLongitude += Math.PI * 2.0;
+ if (testRightLongitude - leftLongitude >= Math.PI) {
+ noLongitudeBound = true;
+ leftLongitude = null;
+ rightLongitude = null;
+ }
+ }
+
+}
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Plane.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Plane.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Plane.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Plane.java Wed Sep 2 19:59:31 2015
@@ -28,6 +28,13 @@ public class Plane extends Vector {
protected final static GeoPoint[] NO_POINTS = new GeoPoint[0];
/** An array with no bounds in it */
protected final static Membership[] NO_BOUNDS = new Membership[0];
+ /** A vertical plane normal to the Y axis */
+ protected final static Plane normalYPlane = new Plane(0.0,1.0,0.0,0.0);
+ /** A vertical plane normal to the X axis */
+ protected final static Plane normalXPlane = new Plane(1.0,0.0,0.0,0.0);
+ /** A vertical plane normal to the Z axis */
+ protected final static Plane normalZPlane = new Plane(0.0,0.0,1.0,0.0);
+
/** Ax + By + Cz + D = 0 */
public final double D;
@@ -88,12 +95,12 @@ public class Plane extends Vector {
this.D = D;
}
- /** Construct the most accurate normalized, vertical plane given a set of points. If none of the points can determine
- * the plane, return null.
- * @param planePoints is a set of points to choose from. The best one for constructing the most precise normal plane is picked.
- * @return the normal plane
+ /** Construct the most accurate normalized plane through an x-y point and including the Z axis.
+ * If none of the points can determine the plane, return null.
+ * @param planePoints is a set of points to choose from. The best one for constructing the most precise plane is picked.
+ * @return the plane
*/
- public static Plane constructNormalizedVerticalPlane(final Vector... planePoints) {
+ public static Plane constructNormalizedZPlane(final Vector... planePoints) {
// Pick the best one (with the greatest x-y distance)
double bestDistance = 0.0;
Vector bestPoint = null;
@@ -104,19 +111,86 @@ public class Plane extends Vector {
bestPoint = point;
}
}
- return constructNormalizedVerticalPlane(bestPoint.x, bestPoint.y);
+ return constructNormalizedZPlane(bestPoint.x, bestPoint.y);
+ }
+
+ /** Construct the most accurate normalized plane through an x-z point and including the Y axis.
+ * If none of the points can determine the plane, return null.
+ * @param planePoints is a set of points to choose from. The best one for constructing the most precise plane is picked.
+ * @return the plane
+ */
+ public static Plane constructNormalizedYPlane(final Vector... planePoints) {
+ // Pick the best one (with the greatest x-z distance)
+ double bestDistance = 0.0;
+ Vector bestPoint = null;
+ for (final Vector point : planePoints) {
+ final double pointDist = point.x * point.x + point.z * point.z;
+ if (pointDist > bestDistance) {
+ bestDistance = pointDist;
+ bestPoint = point;
+ }
+ }
+ return constructNormalizedYPlane(bestPoint.x, bestPoint.z, 0.0);
}
- /** Construct a normalized, vertical plane through an x-y point. If the x-y point is at (0,0), return null.
+ /** Construct the most accurate normalized plane through an y-z point and including the X axis.
+ * If none of the points can determine the plane, return null.
+ * @param planePoints is a set of points to choose from. The best one for constructing the most precise plane is picked.
+ * @return the plane
+ */
+ public static Plane constructNormalizedXPlane(final Vector... planePoints) {
+ // Pick the best one (with the greatest y-z distance)
+ double bestDistance = 0.0;
+ Vector bestPoint = null;
+ for (final Vector point : planePoints) {
+ final double pointDist = point.y * point.y + point.z * point.z;
+ if (pointDist > bestDistance) {
+ bestDistance = pointDist;
+ bestPoint = point;
+ }
+ }
+ return constructNormalizedXPlane(bestPoint.y, bestPoint.z, 0.0);
+ }
+
+ /** Construct a normalized plane through an x-y point and including the Z axis.
+ * If the x-y point is at (0,0), return null.
* @param x is the x value.
* @param y is the y value.
- * @return a vertical plane passing through the center and (x,y,0).
+ * @return a plane passing through the Z axis and (x,y,0).
*/
- public static Plane constructNormalizedVerticalPlane(final double x, final double y) {
+ public static Plane constructNormalizedZPlane(final double x, final double y) {
if (Math.abs(x) < MINIMUM_RESOLUTION && Math.abs(y) < MINIMUM_RESOLUTION)
return null;
final double denom = 1.0 / Math.sqrt(x*x + y*y);
- return new Plane(x * denom, y * denom);
+ return new Plane(y * denom, -x * denom, 0.0, 0.0);
+ }
+
+ /** Construct a normalized plane through an x-z point and parallel to the Y axis.
+ * If the x-z point is at (0,0), return null.
+ * @param x is the x value.
+ * @param z is the z value.
+ * @param DValue is the offset from the origin for the plane.
+ * @return a plane parallel to the Y axis and perpendicular to the x and z values given.
+ */
+ public static Plane constructNormalizedYPlane(final double x, final double z, final double DValue) {
+ if (Math.abs(x) < MINIMUM_RESOLUTION && Math.abs(z) < MINIMUM_RESOLUTION)
+ return null;
+ final double denom = 1.0 / Math.sqrt(x*x + z*z);
+ return new Plane(z * denom, 0.0, -x * denom, DValue);
+ }
+
+ /** Construct a normalized plane through a y-z point and parallel to the X axis.
+ * If the y-z point is at (0,0), return null.
+ * @param y is the y value.
+ * @param z is the z value.
+ * @param DValue is the offset from the origin for the plane.
+ * @return a plane parallel to the X axis and perpendicular to the y and z values given.
+ */
+ public static Plane constructNormalizedXPlane(final double y, final double z, final double DValue) {
+ if (Math.abs(y) < MINIMUM_RESOLUTION && Math.abs(z) < MINIMUM_RESOLUTION)
+ return null;
+ final double denom = 1.0 / Math.sqrt(y*y + z*z);
+ return new Plane(0.0, z * denom, -y * denom, DValue);
}
/**
@@ -695,35 +769,149 @@ public class Plane extends Vector {
throw new RuntimeException("Intersection point not on ellipsoid; point="+point);
}
*/
-
+
/**
- * Accumulate bounds information for this plane, intersected with another plane
- * and with the unit sphere.
- * Updates both latitude and longitude information, using max/min points found
+ * Accumulate (x,y,z) bounds information for this plane, intersected with the unit sphere.
+ * Updates min/max information, using max/min points found
* within the specified bounds.
*
- * @param planetModel is the planet model to use to determine bounding points
- * @param q is the plane to intersect with.
- * @param boundsInfo is the info to update with additional bounding information.
+ * @param planetModel is the planet model to use in determining bounds.
+ * @param boundsInfo is the xyz info to update with additional bounding information.
* @param bounds are the surfaces delineating what's inside the shape.
*/
- public void recordBounds(final PlanetModel planetModel, final Plane q, final Bounds boundsInfo, final Membership... bounds) {
- final GeoPoint[] intersectionPoints = findIntersections(planetModel, q, bounds, NO_BOUNDS);
- for (GeoPoint intersectionPoint : intersectionPoints) {
- boundsInfo.addPoint(intersectionPoint);
+ public void recordBounds(final PlanetModel planetModel, final XYZBounds boundsInfo, final Membership... bounds) {
+ // Basic plan is to do three intersections of the plane and the planet.
+ // For min/max x, we intersect a vertical plane such that y = 0.
+ // For min/max y, we intersect a vertical plane such that x = 0.
+ // For min/max z, we intersect a vertical plane that is chosen to go through the high point of the arc.
+ // For clarity, load local variables with good names
+ final double A = this.x;
+ final double B = this.y;
+ final double C = this.z;
+
+ // For the X and Y values, we need a D value, which is the AVERAGE D value
+ // for two planes that pass through the two Z points determined here, for the axis in question.
+ final GeoPoint[] zPoints;
+ if (!boundsInfo.isSmallestMinX(planetModel) || !boundsInfo.isLargestMaxX(planetModel) ||
+ !boundsInfo.isSmallestMinY(planetModel) || !boundsInfo.isLargestMaxY(planetModel)) {
+ if ((Math.abs(A) >= MINIMUM_RESOLUTION || Math.abs(B) >= MINIMUM_RESOLUTION)) {
+ // We need unconstrained values in order to compute D
+ zPoints = findIntersections(planetModel, constructNormalizedZPlane(A,B), NO_BOUNDS, NO_BOUNDS);
+ if (zPoints.length == 0) {
+ // No intersections, so plane never intersects world.
+ //System.err.println(" plane never intersects world");
+ return;
+ }
+ //for (final GeoPoint p : zPoints) {
+ // System.err.println("zPoint: "+p);
+ //}
+ } else {
+ zPoints = null;
+ }
+ } else {
+ zPoints = null;
}
- }
+ // Do Z.
+ if (!boundsInfo.isSmallestMinZ(planetModel) || !boundsInfo.isLargestMaxZ(planetModel)) {
+ //System.err.println(" computing Z bound");
+ // Compute Z bounds for this arc
+ // With ellipsoids, we really have only one viable way to do this computation.
+ // Specifically, we compute an appropriate vertical plane, based on the current plane's x-y orientation, and
+ // then intersect it with this one and with the ellipsoid. This gives us zero, one, or two points to use
+ // as bounds.
+ // There is one special case: horizontal circles. These require TWO vertical planes: one for the x, and one for
+ // the y, and we use all four resulting points in the bounds computation.
+ if ((Math.abs(A) >= MINIMUM_RESOLUTION || Math.abs(B) >= MINIMUM_RESOLUTION)) {
+ // NOT a degenerate case
+ //System.err.println(" not degenerate");
+ final Plane normalizedZPlane = constructNormalizedZPlane(A,B);
+ final GeoPoint[] points = findIntersections(planetModel, normalizedZPlane, bounds, NO_BOUNDS);
+ for (final GeoPoint point : points) {
+ assert planetModel.pointOnSurface(point);
+ //System.err.println(" Point = "+point+"; this.evaluate(point)="+this.evaluate(point)+"; normalizedZPlane.evaluate(point)="+normalizedZPlane.evaluate(point));
+ addPoint(boundsInfo, bounds, point);
+ }
+ } else {
+ // Since a==b==0, any plane including the Z axis suffices.
+ //System.err.println(" Perpendicular to z");
+ final GeoPoint[] points = findIntersections(planetModel, normalYPlane, NO_BOUNDS, NO_BOUNDS);
+ boundsInfo.addZValue(points[0]);
+ }
+ }
+
+ if (!boundsInfo.isSmallestMinX(planetModel) || !boundsInfo.isLargestMaxX(planetModel)) {
+ //System.err.println(" computing X bound");
+ if ((Math.abs(B) >= MINIMUM_RESOLUTION || Math.abs(C) >= MINIMUM_RESOLUTION)) {
+ // NOT a degenerate case. Compute D.
+ //System.err.println(" not degenerate; B="+B+"; C="+C);
+ final Plane originPlane = constructNormalizedXPlane(B,C,0.0);
+ double DValue = 0.0;
+ if (zPoints != null) {
+ for (final GeoPoint p : zPoints) {
+ final double zValue = originPlane.evaluate(p);
+ //System.err.println(" originPlane.evaluate(zpoint)="+zValue);
+ DValue += zValue;
+ }
+ DValue /= (double)zPoints.length;
+ }
+ final Plane normalizedXPlane = constructNormalizedXPlane(B,C,-DValue);
+ final GeoPoint[] points = findIntersections(planetModel, normalizedXPlane, bounds, NO_BOUNDS);
+ for (final GeoPoint point : points) {
+ assert planetModel.pointOnSurface(point);
+ //System.err.println(" Point = "+point+"; this.evaluate(point)="+this.evaluate(point)+"; normalizedXPlane.evaluate(point)="+normalizedXPlane.evaluate(point));
+ addPoint(boundsInfo, bounds, point);
+ }
+ } else {
+ // Since b==c==0, any plane including the X axis suffices.
+ //System.err.println(" Perpendicular to x");
+ final GeoPoint[] points = findIntersections(planetModel, normalZPlane, NO_BOUNDS, NO_BOUNDS);
+ boundsInfo.addXValue(points[0]);
+ }
+ }
+
+ // Do Y
+ if (!boundsInfo.isSmallestMinY(planetModel) || !boundsInfo.isLargestMaxY(planetModel)) {
+ //System.err.println(" computing Y bound");
+ if ((Math.abs(A) >= MINIMUM_RESOLUTION || Math.abs(C) >= MINIMUM_RESOLUTION)) {
+ // NOT a degenerate case. Compute D.
+ //System.err.println(" not degenerate");
+ final Plane originPlane = constructNormalizedYPlane(A,C,0.0);
+ double DValue = 0.0;
+ if (zPoints != null) {
+ for (final GeoPoint p : zPoints) {
+ DValue += originPlane.evaluate(p);
+ }
+ DValue /= (double)zPoints.length;
+ }
+ final Plane normalizedYPlane = constructNormalizedYPlane(A,C,-DValue);
+ final GeoPoint[] points = findIntersections(planetModel, normalizedYPlane, bounds, NO_BOUNDS);
+ for (final GeoPoint point : points) {
+ assert planetModel.pointOnSurface(point);
+ //System.err.println(" Point = "+point+"; this.evaluate(point)="+this.evaluate(point)+"; normalizedYPlane.evaluate(point)="+normalizedYPlane.evaluate(point));
+ addPoint(boundsInfo, bounds, point);
+ }
+ } else {
+ // Since a==c==0, any plane including the Y axis suffices.
+ // It doesn't matter that we may discard the point due to bounds, because if there are bounds, we'll have endpoints
+ // that will be tallied separately.
+ //System.err.println(" Perpendicular to y");
+ final GeoPoint[] points = findIntersections(planetModel, normalXPlane, NO_BOUNDS, NO_BOUNDS);
+ boundsInfo.addYValue(points[0]);
+ }
+ }
+ }
+
/**
* Accumulate bounds information for this plane, intersected with the unit sphere.
* Updates both latitude and longitude information, using max/min points found
* within the specified bounds.
*
* @param planetModel is the planet model to use in determining bounds.
- * @param boundsInfo is the info to update with additional bounding information.
+ * @param boundsInfo is the lat/lon info to update with additional bounding information.
* @param bounds are the surfaces delineating what's inside the shape.
*/
- public void recordBounds(final PlanetModel planetModel, final Bounds boundsInfo, final Membership... bounds) {
+ public void recordBounds(final PlanetModel planetModel, final LatLonBounds boundsInfo, final Membership... bounds) {
// For clarity, load local variables with good names
final double A = this.x;
final double B = this.y;
@@ -741,18 +929,15 @@ public class Plane extends Vector {
if ((Math.abs(A) >= MINIMUM_RESOLUTION || Math.abs(B) >= MINIMUM_RESOLUTION)) {
// NOT a horizontal circle!
//System.err.println(" Not a horizontal circle");
- final Plane verticalPlane = constructNormalizedVerticalPlane(A,B);
- final GeoPoint[] points = findIntersections(planetModel, verticalPlane, NO_BOUNDS, NO_BOUNDS);
+ final Plane verticalPlane = constructNormalizedZPlane(A,B);
+ final GeoPoint[] points = findIntersections(planetModel, verticalPlane, bounds, NO_BOUNDS);
for (final GeoPoint point : points) {
- addPoint(boundsInfo, bounds, point.x, point.y, point.z);
+ addPoint(boundsInfo, bounds, point);
}
} else {
- // Horizontal circle. Since a==b, one vertical plane suffices.
- final Plane verticalPlane = new Plane(1.0,0.0);
- final GeoPoint[] points = findIntersections(planetModel, verticalPlane, NO_BOUNDS, NO_BOUNDS);
- // There will always be two points; we only need one.
- final GeoPoint point = points[0];
- boundsInfo.addHorizontalCircle(point.z/Math.sqrt(point.x * point.x + point.y * point.y + point.z * point.z));
+ // Horizontal circle. Since a==b, any vertical plane suffices.
+ final GeoPoint[] points = findIntersections(planetModel, normalXPlane, NO_BOUNDS, NO_BOUNDS);
+ boundsInfo.addZValue(points[0]);
}
//System.err.println("Done latitude bounds");
}
@@ -808,7 +993,7 @@ public class Plane extends Vector {
double y0 = -b / (2.0 * a);
double x0 = (-D - B * y0) / A;
double z0 = 0.0;
- addPoint(boundsInfo, bounds, x0, y0, z0);
+ addPoint(boundsInfo, bounds, new GeoPoint(x0, y0, z0));
} else if (sqrtClause > 0.0) {
double sqrtResult = Math.sqrt(sqrtClause);
double denom = 1.0 / (2.0 * a);
@@ -823,8 +1008,8 @@ public class Plane extends Vector {
double z0a = 0.0;
double z0b = 0.0;
- addPoint(boundsInfo, bounds, x0a, y0a, z0a);
- addPoint(boundsInfo, bounds, x0b, y0b, z0b);
+ addPoint(boundsInfo, bounds, new GeoPoint(x0a, y0a, z0a));
+ addPoint(boundsInfo, bounds, new GeoPoint(x0b, y0b, z0b));
}
} else {
@@ -841,7 +1026,7 @@ public class Plane extends Vector {
double x0 = -b / (2.0 * a);
double y0 = (-D - A * x0) / B;
double z0 = 0.0;
- addPoint(boundsInfo, bounds, x0, y0, z0);
+ addPoint(boundsInfo, bounds, new GeoPoint(x0, y0, z0));
} else if (sqrtClause > 0.0) {
double sqrtResult = Math.sqrt(sqrtClause);
double denom = 1.0 / (2.0 * a);
@@ -854,8 +1039,8 @@ public class Plane extends Vector {
double z0a = 0.0;
double z0b = 0.0;
- addPoint(boundsInfo, bounds, x0a, y0a, z0a);
- addPoint(boundsInfo, bounds, x0b, y0b, z0b);
+ addPoint(boundsInfo, bounds, new GeoPoint(x0a, y0a, z0a));
+ addPoint(boundsInfo, bounds, new GeoPoint(x0b, y0b, z0b));
}
}
}
@@ -949,7 +1134,7 @@ public class Plane extends Vector {
double x0 = (-2.0 * J - I * y0) / H;
double z0 = (-A * x0 - B * y0 - D) / C;
- addPoint(boundsInfo, bounds, x0, y0, z0);
+ addPoint(boundsInfo, bounds, new GeoPoint(x0, y0, z0));
} else if (sqrtClause > 0.0) {
//System.err.println(" Two solutions");
double sqrtResult = Math.sqrt(sqrtClause);
@@ -964,8 +1149,8 @@ public class Plane extends Vector {
double z0a = (-A * x0a - B * y0a - D) * Cdenom;
double z0b = (-A * x0b - B * y0b - D) * Cdenom;
- addPoint(boundsInfo, bounds, x0a, y0a, z0a);
- addPoint(boundsInfo, bounds, x0b, y0b, z0b);
+ addPoint(boundsInfo, bounds, new GeoPoint(x0a, y0a, z0a));
+ addPoint(boundsInfo, bounds, new GeoPoint(x0b, y0b, z0b));
}
} else {
@@ -1001,7 +1186,7 @@ public class Plane extends Vector {
double z0 = (-A * x0 - B * y0 - D) / C;
// Verify that x&y fulfill the equation
// 2Ex^2 + 2Fy^2 + 2Gxy + Hx + Iy = 0
- addPoint(boundsInfo, bounds, x0, y0, z0);
+ addPoint(boundsInfo, bounds, new GeoPoint(x0, y0, z0));
} else if (sqrtClause > 0.0) {
//System.err.println(" Two solutions");
double sqrtResult = Math.sqrt(sqrtClause);
@@ -1016,8 +1201,8 @@ public class Plane extends Vector {
double z0a = (-A * x0a - B * y0a - D) * Cdenom;
double z0b = (-A * x0b - B * y0b - D) * Cdenom;
- addPoint(boundsInfo, bounds, x0a, y0a, z0a);
- addPoint(boundsInfo, bounds, x0b, y0b, z0b);
+ addPoint(boundsInfo, bounds, new GeoPoint(x0a, y0a, z0a));
+ addPoint(boundsInfo, bounds, new GeoPoint(x0b, y0b, z0b));
}
}
}
@@ -1029,10 +1214,26 @@ public class Plane extends Vector {
/** Add a point to boundsInfo if within a specifically bounded area.
* @param boundsInfo is the object to be modified.
* @param bounds is the area that the point must be within.
+ * @param point is the point.
+ */
+ protected static void addPoint(final Bounds boundsInfo, final Membership[] bounds, final GeoPoint point) {
+ // Make sure the discovered point is within the bounds
+ for (Membership bound : bounds) {
+ if (!bound.isWithin(point))
+ return;
+ }
+ // Add the point
+ boundsInfo.addPoint(point);
+ }
+
+ /** Add a point to boundsInfo if within a specifically bounded area.
+ * @param boundsInfo is the object to be modified.
+ * @param bounds is the area that the point must be within.
* @param x is the x value.
* @param y is the y value.
* @param z is the z value.
*/
+ /*
protected static void addPoint(final Bounds boundsInfo, final Membership[] bounds, final double x, final double y, final double z) {
//System.err.println(" Want to add point x="+x+" y="+y+" z="+z);
// Make sure the discovered point is within the bounds
@@ -1045,6 +1246,7 @@ public class Plane extends Vector {
//System.out.println("Adding point x="+x+" y="+y+" z="+z);
boundsInfo.addPoint(x, y, z);
}
+ */
/**
* Determine whether the plane intersects another plane within the
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PlanetModel.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PlanetModel.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PlanetModel.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/PlanetModel.java Wed Sep 2 19:59:31 2015
@@ -65,6 +65,14 @@ public class PlanetModel {
public final GeoPoint NORTH_POLE;
/** South pole */
public final GeoPoint SOUTH_POLE;
+ /** Min X pole */
+ public final GeoPoint MIN_X_POLE;
+ /** Max X pole */
+ public final GeoPoint MAX_X_POLE;
+ /** Min Y pole */
+ public final GeoPoint MIN_Y_POLE;
+ /** Max Y pole */
+ public final GeoPoint MAX_Y_POLE;
/** Constructor.
* @param ab is the x/y scaling factor.
@@ -81,6 +89,10 @@ public class PlanetModel {
this.inverseCSquared = inverseC * inverseC;
this.NORTH_POLE = new GeoPoint(c, 0.0, 0.0, 1.0, Math.PI * 0.5, 0.0);
this.SOUTH_POLE = new GeoPoint(c, 0.0, 0.0, -1.0, -Math.PI * 0.5, 0.0);
+ this.MIN_X_POLE = new GeoPoint(ab, -1.0, 0.0, 0.0, 0.0, -Math.PI);
+ this.MAX_X_POLE = new GeoPoint(ab, 1.0, 0.0, 0.0, 0.0, 0.0);
+ this.MIN_Y_POLE = new GeoPoint(ab, 0.0, -1.0, 0.0, 0.0, -Math.PI * 0.5);
+ this.MAX_Y_POLE = new GeoPoint(ab, 0.0, 1.0, 0.0, 0.0, Math.PI * 0.5);
}
/** Find the minimum magnitude of all points on the ellipsoid.
@@ -97,6 +109,86 @@ public class PlanetModel {
return Math.max(this.ab, this.c);
}
+ /** Find the minimum x value.
+ *@return the minimum X value.
+ */
+ public double getMinimumXValue() {
+ return -this.ab;
+ }
+
+ /** Find the maximum x value.
+ *@return the maximum X value.
+ */
+ public double getMaximumXValue() {
+ return this.ab;
+ }
+
+ /** Find the minimum y value.
+ *@return the minimum Y value.
+ */
+ public double getMinimumYValue() {
+ return -this.ab;
+ }
+
+ /** Find the maximum y value.
+ *@return the maximum Y value.
+ */
+ public double getMaximumYValue() {
+ return this.ab;
+ }
+
+ /** Find the minimum z value.
+ *@return the minimum Z value.
+ */
+ public double getMinimumZValue() {
+ return -this.c;
+ }
+
+ /** Find the maximum z value.
+ *@return the maximum Z value.
+ */
+ public double getMaximumZValue() {
+ return this.c;
+ }
+
+ /** Check if point is on surface.
+ * @param v is the point to check.
+ * @return true if the point is on the planet surface.
+ */
+ public boolean pointOnSurface(final Vector v) {
+ return pointOnSurface(v.x, v.y, v.z);
+ }
+
+ /** Check if point is on surface.
+ * @param x is the x coord.
+ * @param y is the y coord.
+ * @param z is the z coord.
+ */
+ public boolean pointOnSurface(final double x, final double y, final double z) {
+ // Equation of planet surface is:
+ // x^2 / a^2 + y^2 / b^2 + z^2 / c^2 - 1 = 0
+ return Math.abs((x * x + y * y) * inverseAb * inverseAb + z * z * inverseC * inverseC - 1.0) < Vector.MINIMUM_RESOLUTION;
+ }
+
+ /** Check if point is outside surface.
+ * @param v is the point to check.
+ * @return true if the point is outside the planet surface.
+ */
+ public boolean pointOutside(final Vector v) {
+ return pointOutside(v.x, v.y, v.z);
+ }
+
+ /** Check if point is outside surface.
+ * @param x is the x coord.
+ * @param y is the y coord.
+ * @param z is the z coord.
+ */
+ public boolean pointOutside(final double x, final double y, final double z) {
+ // Equation of planet surface is:
+ // x^2 / a^2 + y^2 / b^2 + z^2 / c^2 - 1 = 0
+ return (x * x + y * y) * inverseAb * inverseAb + z * z * inverseC * inverseC - 1.0 > Vector.MINIMUM_RESOLUTION;
+ }
+
/** Compute surface distance between two points.
* @param p1 is the first point.
* @param p2 is the second point.
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/SidedPlane.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/SidedPlane.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/SidedPlane.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/SidedPlane.java Wed Sep 2 19:59:31 2015
@@ -48,6 +48,8 @@ public class SidedPlane extends Plane im
public SidedPlane(Vector p, Vector A, Vector B) {
super(A, B);
sigNum = Math.signum(evaluate(p));
+ if (sigNum == 0.0)
+ throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
}
/**
@@ -60,6 +62,8 @@ public class SidedPlane extends Plane im
public SidedPlane(Vector p, final PlanetModel planetModel, double sinLat) {
super(planetModel, sinLat);
sigNum = Math.signum(evaluate(p));
+ if (sigNum == 0.0)
+ throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
}
/**
@@ -72,6 +76,8 @@ public class SidedPlane extends Plane im
public SidedPlane(Vector p, double x, double y) {
super(x, y);
sigNum = Math.signum(evaluate(p));
+ if (sigNum == 0.0)
+ throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
}
/**
@@ -84,6 +90,24 @@ public class SidedPlane extends Plane im
public SidedPlane(Vector p, Vector v, double D) {
super(v, D);
sigNum = Math.signum(evaluate(p));
+ if (sigNum == 0.0)
+ throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
+ }
+
+ /**
+ * Construct a sided plane with a normal vector and offset.
+ *
+ * @param pX X coord of point to evaluate.
+ * @param pY Y coord of point to evaluate.
+ * @param pZ Z coord of point to evaluate.
+ * @param v is the normal vector.
+ * @param D is the origin offset for the plan.
+ */
+ public SidedPlane(double pX, double pY, double pZ, Vector v, double D) {
+ super(v, D);
+ sigNum = Math.signum(evaluate(pX,pY,pZ));
+ if (sigNum == 0.0)
+ throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
}
/** Construct a sided plane from two points and a third normal vector.
Modified: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Vector.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Vector.java?rev=1700883&r1=1700882&r2=1700883&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Vector.java (original)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/Vector.java Wed Sep 2 19:59:31 2015
@@ -28,7 +28,7 @@ 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-12;
+ public static final double MINIMUM_RESOLUTION = 5.0e-13;
/**
* For squared quantities, the bound is squared too.
*/
Added: lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZBounds.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZBounds.java?rev=1700883&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZBounds.java (added)
+++ lucene/dev/trunk/lucene/spatial3d/src/java/org/apache/lucene/geo3d/XYZBounds.java Wed Sep 2 19:59:31 2015
@@ -0,0 +1,268 @@
+package org.apache.lucene.geo3d;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * An object for accumulating XYZ bounds information.
+ *
+ * @lucene.experimental
+ */
+public class XYZBounds implements Bounds {
+
+ /** A 'fudge factor', which is added to maximums and subtracted from minimums,
+ * in order to compensate for potential error deltas. This would not be necessary
+ * except that our 'bounds' is defined as always equaling or exceeding the boundary
+ * of the shape, and we cannot guarantee that without making MINIMUM_RESOLUTION
+ * unacceptably large.
+ */
+ protected static final double FUDGE_FACTOR = Vector.MINIMUM_RESOLUTION * 2e6;
+
+ /** Minimum x */
+ protected Double minX = null;
+ /** Maximum x */
+ protected Double maxX = null;
+ /** Minimum y */
+ protected Double minY = null;
+ /** Maximum y */
+ protected Double maxY = null;
+ /** Minimum z */
+ protected Double minZ = null;
+ /** Maximum z */
+ protected Double maxZ = null;
+
+ /** Set to true if no longitude bounds can be stated */
+ protected boolean noLongitudeBound = false;
+ /** Set to true if no top latitude bound can be stated */
+ protected boolean noTopLatitudeBound = false;
+ /** Set to true if no bottom latitude bound can be stated */
+ protected boolean noBottomLatitudeBound = false;
+
+ /** Construct an empty bounds object */
+ public XYZBounds() {
+ }
+
+ // Accessor methods
+
+ /** Return the minimum X value.
+ *@return minimum X value.
+ */
+ public Double getMinimumX() {
+ return minX;
+ }
+
+ /** Return the maximum X value.
+ *@return maximum X value.
+ */
+ public Double getMaximumX() {
+ return maxX;
+ }
+
+ /** Return the minimum Y value.
+ *@return minimum Y value.
+ */
+ public Double getMinimumY() {
+ return minY;
+ }
+
+ /** Return the maximum Y value.
+ *@return maximum Y value.
+ */
+ public Double getMaximumY() {
+ return maxY;
+ }
+
+ /** Return the minimum Z value.
+ *@return minimum Z value.
+ */
+ public Double getMinimumZ() {
+ return minZ;
+ }
+
+ /** Return the maximum Z value.
+ *@return maximum Z value.
+ */
+ public Double getMaximumZ() {
+ return maxZ;
+ }
+
+ /** Return true if minX is as small as the planet model allows.
+ *@return true if minX has reached its bound.
+ */
+ public boolean isSmallestMinX(final PlanetModel planetModel) {
+ if (minX == null)
+ return false;
+ return minX - planetModel.getMinimumXValue() < Vector.MINIMUM_RESOLUTION;
+ }
+
+ /** Return true if maxX is as large as the planet model allows.
+ *@return true if maxX has reached its bound.
+ */
+ public boolean isLargestMaxX(final PlanetModel planetModel) {
+ if (maxX == null)
+ return false;
+ return planetModel.getMaximumXValue() - maxX < Vector.MINIMUM_RESOLUTION;
+ }
+
+ /** Return true if minY is as small as the planet model allows.
+ *@return true if minY has reached its bound.
+ */
+ public boolean isSmallestMinY(final PlanetModel planetModel) {
+ if (minY == null)
+ return false;
+ return minY - planetModel.getMinimumYValue() < Vector.MINIMUM_RESOLUTION;
+ }
+
+ /** Return true if maxY is as large as the planet model allows.
+ *@return true if maxY has reached its bound.
+ */
+ public boolean isLargestMaxY(final PlanetModel planetModel) {
+ if (maxY == null)
+ return false;
+ return planetModel.getMaximumYValue() - maxY < Vector.MINIMUM_RESOLUTION;
+ }
+
+ /** Return true if minZ is as small as the planet model allows.
+ *@return true if minZ has reached its bound.
+ */
+ public boolean isSmallestMinZ(final PlanetModel planetModel) {
+ if (minZ == null)
+ return false;
+ return minZ - planetModel.getMinimumZValue() < Vector.MINIMUM_RESOLUTION;
+ }
+
+ /** Return true if maxZ is as large as the planet model allows.
+ *@return true if maxZ has reached its bound.
+ */
+ public boolean isLargestMaxZ(final PlanetModel planetModel) {
+ if (maxZ == null)
+ return false;
+ return planetModel.getMaximumZValue() - maxZ < Vector.MINIMUM_RESOLUTION;
+ }
+
+ // Modification methods
+
+ @Override
+ public Bounds addPlane(final PlanetModel planetModel, final Plane plane, final Membership... bounds) {
+ plane.recordBounds(planetModel, this, bounds);
+ return this;
+ }
+
+ /** Add a horizontal plane to the bounds description.
+ * This method should EITHER use the supplied latitude, OR use the supplied
+ * plane, depending on what is most efficient.
+ *@param planetModel is the planet model.
+ *@param latitude is the latitude.
+ *@param horizontalPlane is the plane.
+ *@param bounds are the constraints on the plane.
+ *@return updated Bounds object.
+ */
+ public Bounds addHorizontalPlane(final PlanetModel planetModel,
+ final double latitude,
+ final Plane horizontalPlane,
+ final Membership... bounds) {
+ return addPlane(planetModel, horizontalPlane, bounds);
+ }
+
+ /** Add a vertical plane to the bounds description.
+ * This method should EITHER use the supplied longitude, OR use the supplied
+ * plane, depending on what is most efficient.
+ *@param planetModel is the planet model.
+ *@param longitude is the longitude.
+ *@param verticalPlane is the plane.
+ *@param bounds are the constraints on the plane.
+ *@return updated Bounds object.
+ */
+ public Bounds addVerticalPlane(final PlanetModel planetModel,
+ final double longitude,
+ final Plane verticalPlane,
+ final Membership... bounds) {
+ return addPlane(planetModel, verticalPlane, bounds);
+ }
+
+ @Override
+ public Bounds addXValue(final GeoPoint point) {
+ final double x = point.x;
+ final double small = x - FUDGE_FACTOR;
+ if (minX == null || minX > small) {
+ minX = new Double(small);
+ }
+ final double large = x + FUDGE_FACTOR;
+ if (maxX == null || maxX < large) {
+ maxX = new Double(large);
+ }
+ return this;
+ }
+
+ @Override
+ public Bounds addYValue(final GeoPoint point) {
+ final double y = point.y;
+ final double small = y - FUDGE_FACTOR;
+ if (minY == null || minY > small) {
+ minY = new Double(small);
+ }
+ final double large = y + FUDGE_FACTOR;
+ if (maxY == null || maxY < large) {
+ maxY = new Double(large);
+ }
+ return this;
+ }
+
+ @Override
+ public Bounds addZValue(final GeoPoint point) {
+ final double z = point.z;
+ final double small = z - FUDGE_FACTOR;
+ if (minZ == null || minZ > small) {
+ minZ = new Double(small);
+ }
+ final double large = z + FUDGE_FACTOR;
+ if (maxZ == null || maxZ < large) {
+ maxZ = new Double(large);
+ }
+ return this;
+ }
+
+ @Override
+ public Bounds addPoint(final GeoPoint point) {
+ return addXValue(point).addYValue(point).addZValue(point);
+ }
+
+ @Override
+ public Bounds isWide() {
+ // No specific thing we need to do.
+ return this;
+ }
+
+ @Override
+ public Bounds noLongitudeBound() {
+ // No specific thing we need to do.
+ return this;
+ }
+
+ @Override
+ public Bounds noTopLatitudeBound() {
+ // No specific thing we need to do.
+ return this;
+ }
+
+ @Override
+ public Bounds noBottomLatitudeBound() {
+ // No specific thing we need to do.
+ return this;
+ }
+
+}