mirror of https://github.com/apache/lucene.git
LUCENE-6487: Geo3D with WGS84 in-progress with David's mods
(PlanetModel, and refactor of Geo3dShapeRectRelationTestCase) git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/branches/lucene6487@1681907 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4dd402650f
commit
560f3a1a01
|
@ -28,6 +28,7 @@ import org.apache.lucene.spatial.spatial4j.geo3d.GeoArea;
|
|||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoAreaFactory;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoPoint;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoShape;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.PlanetModel;
|
||||
|
||||
/**
|
||||
* A 3D planar geometry based Spatial4j Shape implementation.
|
||||
|
@ -38,17 +39,23 @@ public class Geo3dShape implements Shape {
|
|||
|
||||
public final SpatialContext ctx;
|
||||
public final GeoShape shape;
|
||||
public final PlanetModel planetModel;
|
||||
|
||||
private Rectangle boundingBox = null;
|
||||
|
||||
public final static double RADIANS_PER_DEGREE = Math.PI / 180.0;
|
||||
public final static double DEGREES_PER_RADIAN = 1.0 / RADIANS_PER_DEGREE;
|
||||
|
||||
public Geo3dShape(GeoShape shape, SpatialContext ctx) {
|
||||
public Geo3dShape(final GeoShape shape, final SpatialContext ctx) {
|
||||
this(PlanetModel.SPHERE, shape, ctx);
|
||||
}
|
||||
|
||||
public Geo3dShape(final PlanetModel planetModel, final GeoShape shape, final SpatialContext ctx) {
|
||||
if (!ctx.isGeo()) {
|
||||
throw new IllegalArgumentException("SpatialContext.isGeo() must be true");
|
||||
}
|
||||
this.ctx = ctx;
|
||||
this.planetModel = planetModel;
|
||||
this.shape = shape;
|
||||
}
|
||||
|
||||
|
@ -64,7 +71,8 @@ public class Geo3dShape implements Shape {
|
|||
|
||||
protected SpatialRelation relate(Rectangle r) {
|
||||
// Construct the right kind of GeoArea first
|
||||
GeoArea geoArea = GeoAreaFactory.makeGeoArea(r.getMaxY() * RADIANS_PER_DEGREE,
|
||||
GeoArea geoArea = GeoAreaFactory.makeGeoArea(planetModel,
|
||||
r.getMaxY() * RADIANS_PER_DEGREE,
|
||||
r.getMinY() * RADIANS_PER_DEGREE,
|
||||
r.getMinX() * RADIANS_PER_DEGREE,
|
||||
r.getMaxX() * RADIANS_PER_DEGREE);
|
||||
|
@ -83,7 +91,7 @@ public class Geo3dShape implements Shape {
|
|||
|
||||
protected SpatialRelation relate(Point p) {
|
||||
// Create a GeoPoint
|
||||
GeoPoint point = new GeoPoint(p.getY()*RADIANS_PER_DEGREE, p.getX()*RADIANS_PER_DEGREE);
|
||||
GeoPoint point = new GeoPoint(planetModel, p.getY()*RADIANS_PER_DEGREE, p.getX()*RADIANS_PER_DEGREE);
|
||||
if (shape.isWithin(point)) {
|
||||
// Point within shape
|
||||
return SpatialRelation.CONTAINS;
|
||||
|
@ -91,7 +99,9 @@ public class Geo3dShape implements Shape {
|
|||
return SpatialRelation.DISJOINT;
|
||||
}
|
||||
|
||||
protected final double ROUNDOFF_ADJUSTMENT = 0.01;
|
||||
// The required size of this adjustment depends on the actual planetary model chosen.
|
||||
// This value is big enough to account for WGS84.
|
||||
protected final double ROUNDOFF_ADJUSTMENT = 0.05;
|
||||
|
||||
@Override
|
||||
public Rectangle getBoundingBox() {
|
||||
|
@ -150,7 +160,7 @@ public class Geo3dShape implements Shape {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Geo3dShape{" + shape + '}';
|
||||
return "Geo3dShape{planetmodel=" + planetModel+", shape="+shape + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -158,11 +168,11 @@ public class Geo3dShape implements Shape {
|
|||
if (!(other instanceof Geo3dShape))
|
||||
return false;
|
||||
Geo3dShape tr = (Geo3dShape)other;
|
||||
return tr.shape.equals(shape);
|
||||
return tr.planetModel.equals(planetModel) && tr.shape.equals(shape);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return shape.hashCode();
|
||||
return planetModel.hashCode() + shape.hashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -254,11 +254,11 @@ public class Bounds {
|
|||
}
|
||||
}
|
||||
|
||||
public Bounds addPoint(Vector v) {
|
||||
public Bounds addPoint(final Vector v) {
|
||||
return addPoint(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
public Bounds addPoint(double x, double y, double z) {
|
||||
public Bounds addPoint(final double x, final double y, final double z) {
|
||||
if (!noLongitudeBound) {
|
||||
// Get a longitude value
|
||||
double longitude = Math.atan2(y, x);
|
||||
|
@ -267,7 +267,7 @@ public class Bounds {
|
|||
}
|
||||
if (!noTopLatitudeBound || !noBottomLatitudeBound) {
|
||||
// Compute a latitude value
|
||||
double latitude = Math.asin(z);
|
||||
double latitude = Math.asin(z/Math.sqrt(z * z + x * x + y * y));
|
||||
addLatitudeBound(latitude);
|
||||
}
|
||||
return this;
|
||||
|
|
|
@ -35,8 +35,8 @@ public class GeoAreaFactory {
|
|||
* @param rightLon is the right longitude
|
||||
* @return a GeoArea corresponding to what was specified.
|
||||
*/
|
||||
public static GeoArea makeGeoArea(double topLat, double bottomLat, double leftLon, double rightLon) {
|
||||
return GeoBBoxFactory.makeGeoBBox(topLat, bottomLat, leftLon, rightLon);
|
||||
public static GeoArea makeGeoArea(final PlanetModel planetModel, final double topLat, final double bottomLat, final double leftLon, final double rightLon) {
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, topLat, bottomLat, leftLon, rightLon);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,13 +29,14 @@ public class GeoBBoxFactory {
|
|||
/**
|
||||
* Create a geobbox of the right kind given the specified bounds.
|
||||
*
|
||||
* @param planetModel is the planet model
|
||||
* @param topLat is the top latitude
|
||||
* @param bottomLat is the bottom latitude
|
||||
* @param leftLon is the left longitude
|
||||
* @param rightLon is the right longitude
|
||||
* @return a GeoBBox corresponding to what was specified.
|
||||
*/
|
||||
public static GeoBBox makeGeoBBox(double topLat, double bottomLat, double leftLon, double rightLon) {
|
||||
public static GeoBBox makeGeoBBox(final PlanetModel planetModel, double topLat, double bottomLat, double leftLon, double rightLon) {
|
||||
//System.err.println("Making rectangle for topLat="+topLat*180.0/Math.PI+", bottomLat="+bottomLat*180.0/Math.PI+", leftLon="+leftLon*180.0/Math.PI+", rightlon="+rightLon*180.0/Math.PI);
|
||||
if (topLat > Math.PI * 0.5)
|
||||
topLat = Math.PI * 0.5;
|
||||
|
@ -47,17 +48,17 @@ public class GeoBBoxFactory {
|
|||
rightLon = Math.PI;
|
||||
if (Math.abs(leftLon + Math.PI) < Vector.MINIMUM_RESOLUTION && Math.abs(rightLon - Math.PI) < Vector.MINIMUM_RESOLUTION) {
|
||||
if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION && Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION)
|
||||
return new GeoWorld();
|
||||
return new GeoWorld(planetModel);
|
||||
if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION) {
|
||||
if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION || Math.abs(topLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION)
|
||||
return new GeoDegeneratePoint(topLat, 0.0);
|
||||
return new GeoDegenerateLatitudeZone(topLat);
|
||||
return new GeoDegeneratePoint(planetModel, topLat, 0.0);
|
||||
return new GeoDegenerateLatitudeZone(planetModel, topLat);
|
||||
}
|
||||
if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION)
|
||||
return new GeoNorthLatitudeZone(bottomLat);
|
||||
return new GeoNorthLatitudeZone(planetModel, bottomLat);
|
||||
else if (Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION)
|
||||
return new GeoSouthLatitudeZone(topLat);
|
||||
return new GeoLatitudeZone(topLat, bottomLat);
|
||||
return new GeoSouthLatitudeZone(planetModel, topLat);
|
||||
return new GeoLatitudeZone(planetModel, topLat, bottomLat);
|
||||
}
|
||||
//System.err.println(" not latitude zone");
|
||||
double extent = rightLon - leftLon;
|
||||
|
@ -65,47 +66,47 @@ public class GeoBBoxFactory {
|
|||
extent += Math.PI * 2.0;
|
||||
if (topLat == Math.PI * 0.5 && bottomLat == -Math.PI * 0.5) {
|
||||
if (Math.abs(leftLon - rightLon) < Vector.MINIMUM_RESOLUTION)
|
||||
return new GeoDegenerateLongitudeSlice(leftLon);
|
||||
return new GeoDegenerateLongitudeSlice(planetModel, leftLon);
|
||||
|
||||
if (extent >= Math.PI)
|
||||
return new GeoWideLongitudeSlice(leftLon, rightLon);
|
||||
return new GeoWideLongitudeSlice(planetModel, leftLon, rightLon);
|
||||
|
||||
return new GeoLongitudeSlice(leftLon, rightLon);
|
||||
return new GeoLongitudeSlice(planetModel, leftLon, rightLon);
|
||||
}
|
||||
//System.err.println(" not longitude slice");
|
||||
if (Math.abs(leftLon - rightLon) < Vector.MINIMUM_RESOLUTION) {
|
||||
if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION)
|
||||
return new GeoDegeneratePoint(topLat, leftLon);
|
||||
return new GeoDegenerateVerticalLine(topLat, bottomLat, leftLon);
|
||||
return new GeoDegeneratePoint(planetModel, topLat, leftLon);
|
||||
return new GeoDegenerateVerticalLine(planetModel, topLat, bottomLat, leftLon);
|
||||
}
|
||||
//System.err.println(" not vertical line");
|
||||
if (extent >= Math.PI) {
|
||||
if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION) {
|
||||
//System.err.println(" wide degenerate line");
|
||||
return new GeoWideDegenerateHorizontalLine(topLat, leftLon, rightLon);
|
||||
return new GeoWideDegenerateHorizontalLine(planetModel, topLat, leftLon, rightLon);
|
||||
}
|
||||
if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION) {
|
||||
return new GeoWideNorthRectangle(bottomLat, leftLon, rightLon);
|
||||
return new GeoWideNorthRectangle(planetModel, bottomLat, leftLon, rightLon);
|
||||
} else if (Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION) {
|
||||
return new GeoWideSouthRectangle(topLat, leftLon, rightLon);
|
||||
return new GeoWideSouthRectangle(planetModel, topLat, leftLon, rightLon);
|
||||
}
|
||||
//System.err.println(" wide rect");
|
||||
return new GeoWideRectangle(topLat, bottomLat, leftLon, rightLon);
|
||||
return new GeoWideRectangle(planetModel, topLat, bottomLat, leftLon, rightLon);
|
||||
}
|
||||
if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION) {
|
||||
if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION || Math.abs(topLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION) {
|
||||
return new GeoDegeneratePoint(topLat, 0.0);
|
||||
return new GeoDegeneratePoint(planetModel, topLat, 0.0);
|
||||
}
|
||||
//System.err.println(" horizontal line");
|
||||
return new GeoDegenerateHorizontalLine(topLat, leftLon, rightLon);
|
||||
return new GeoDegenerateHorizontalLine(planetModel, topLat, leftLon, rightLon);
|
||||
}
|
||||
if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION) {
|
||||
return new GeoNorthRectangle(bottomLat, leftLon, rightLon);
|
||||
return new GeoNorthRectangle(planetModel, bottomLat, leftLon, rightLon);
|
||||
} else if (Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION) {
|
||||
return new GeoSouthRectangle(topLat, leftLon, rightLon);
|
||||
return new GeoSouthRectangle(planetModel, topLat, leftLon, rightLon);
|
||||
}
|
||||
//System.err.println(" rectangle");
|
||||
return new GeoRectangle(topLat, bottomLat, leftLon, rightLon);
|
||||
return new GeoRectangle(planetModel, topLat, bottomLat, leftLon, rightLon);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,11 +23,12 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public abstract class GeoBBoxBase implements GeoBBox {
|
||||
|
||||
protected final static GeoPoint NORTH_POLE = new GeoPoint(0.0, 0.0, 1.0);
|
||||
protected final static GeoPoint SOUTH_POLE = new GeoPoint(0.0, 0.0, -1.0);
|
||||
public abstract class GeoBaseBBox extends GeoBaseShape implements GeoBBox {
|
||||
|
||||
public GeoBaseBBox(final PlanetModel planetModel) {
|
||||
super(planetModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract boolean isWithin(final Vector point);
|
||||
|
||||
|
@ -45,6 +46,9 @@ public abstract class GeoBBoxBase implements GeoBBox {
|
|||
} else {
|
||||
foundOutside = true;
|
||||
}
|
||||
if (foundInside && foundOutside) {
|
||||
return SOME_INSIDE;
|
||||
}
|
||||
}
|
||||
if (!foundInside && !foundOutside)
|
||||
return NONE_INSIDE;
|
||||
|
@ -54,5 +58,15 @@ public abstract class GeoBBoxBase implements GeoBBox {
|
|||
return NONE_INSIDE;
|
||||
return SOME_INSIDE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
return super.equals(o);
|
||||
}
|
||||
}
|
||||
|
|
@ -22,11 +22,10 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public abstract class GeoBaseExtendedShape implements GeoShape {
|
||||
protected final static GeoPoint NORTH_POLE = new GeoPoint(0.0, 0.0, 1.0);
|
||||
protected final static GeoPoint SOUTH_POLE = new GeoPoint(0.0, 0.0, -1.0);
|
||||
public abstract class GeoBaseExtendedShape extends GeoBaseShape implements GeoShape {
|
||||
|
||||
public GeoBaseExtendedShape() {
|
||||
public GeoBaseExtendedShape(final PlanetModel planetModel) {
|
||||
super(planetModel);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,12 +82,22 @@ public abstract class GeoBaseExtendedShape implements GeoShape {
|
|||
public Bounds getBounds(Bounds bounds) {
|
||||
if (bounds == null)
|
||||
bounds = new Bounds();
|
||||
if (isWithin(NORTH_POLE)) {
|
||||
if (isWithin(planetModel.NORTH_POLE)) {
|
||||
bounds.noTopLatitudeBound().noLongitudeBound();
|
||||
}
|
||||
if (isWithin(SOUTH_POLE)) {
|
||||
if (isWithin(planetModel.SOUTH_POLE)) {
|
||||
bounds.noBottomLatitudeBound().noLongitudeBound();
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
return super.equals(o);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package org.apache.lucene.spatial.spatial4j.geo3d;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* All bounding box shapes can derive from this base class, which furnishes
|
||||
* some common code
|
||||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public abstract class GeoBaseShape {
|
||||
|
||||
protected final PlanetModel planetModel;
|
||||
|
||||
public GeoBaseShape(final PlanetModel planetModel) {
|
||||
this.planetModel = planetModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return planetModel.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (!(o instanceof GeoBaseShape))
|
||||
return false;
|
||||
return planetModel.equals(((GeoBaseShape)o).planetModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -25,45 +25,42 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape, GeoSizeable {
|
||||
public final GeoPoint center;
|
||||
public final double cutoffAngle;
|
||||
public final double cutoffNormalDistance;
|
||||
public final double cutoffLinearDistance;
|
||||
public final SidedPlane circlePlane;
|
||||
public final GeoPoint[] edgePoints;
|
||||
public static final GeoPoint[] circlePoints = new GeoPoint[0];
|
||||
|
||||
public GeoCircle(final double lat, final double lon, final double cutoffAngle) {
|
||||
super();
|
||||
public GeoCircle(final PlanetModel planetModel, final double lat, final double lon, final double cutoffAngle) {
|
||||
super(planetModel);
|
||||
if (lat < -Math.PI * 0.5 || lat > Math.PI * 0.5)
|
||||
throw new IllegalArgumentException("Latitude out of bounds");
|
||||
if (lon < -Math.PI || lon > Math.PI)
|
||||
throw new IllegalArgumentException("Longitude out of bounds");
|
||||
if (cutoffAngle <= 0.0 || cutoffAngle > Math.PI)
|
||||
throw new IllegalArgumentException("Cutoff angle out of bounds");
|
||||
final double sinAngle = Math.sin(cutoffAngle);
|
||||
final double cosAngle = Math.cos(cutoffAngle);
|
||||
this.center = new GeoPoint(lat, lon);
|
||||
this.cutoffNormalDistance = sinAngle;
|
||||
// Need the chord distance. This is just the chord distance: sqrt((1 - cos(angle))^2 + (sin(angle))^2).
|
||||
final double xDiff = 1.0 - cosAngle;
|
||||
this.cutoffLinearDistance = Math.sqrt(xDiff * xDiff + sinAngle * sinAngle);
|
||||
this.center = new GeoPoint(planetModel, lat, lon);
|
||||
final double magnitude = center.magnitude();
|
||||
// In an ellipsoidal world, cutoff distances make no sense, unfortunately. Only membership
|
||||
// can be used to make in/out determination.
|
||||
this.cutoffAngle = cutoffAngle;
|
||||
this.circlePlane = new SidedPlane(center, center, -cosAngle);
|
||||
// The plane's normal vector needs to be normalized, since we compute D on that basis
|
||||
this.circlePlane = new SidedPlane(center, center.normalize(), -cosAngle * magnitude);
|
||||
|
||||
// Compute a point on the circle boundary.
|
||||
if (cutoffAngle == Math.PI)
|
||||
this.edgePoints = new GeoPoint[0];
|
||||
else {
|
||||
// Move from center only in latitude. Then, if we go past the north pole, adjust the longitude also.
|
||||
double newLat = lat + cutoffAngle;
|
||||
double newLon = lon;
|
||||
if (newLat > Math.PI * 0.5) {
|
||||
newLat = Math.PI - newLat;
|
||||
newLon += Math.PI;
|
||||
// We already have circle plane, which is the definitive determination of the edge of the "circle".
|
||||
// Next, compute vertical plane going through origin and the center point (C = 0, D = 0).
|
||||
Plane verticalPlane = Plane.constructNormalizedVerticalPlane(this.center.x, this.center.y);
|
||||
if (verticalPlane == null) {
|
||||
verticalPlane = new Plane(1.0,0.0);
|
||||
}
|
||||
while (newLon > Math.PI) {
|
||||
newLon -= Math.PI * 2.0;
|
||||
// Finally, use Plane.findIntersections() to find the intersection points.
|
||||
final GeoPoint edgePoint = this.circlePlane.getSampleIntersectionPoint(planetModel, verticalPlane);
|
||||
if (edgePoint == null) {
|
||||
throw new RuntimeException("Could not find edge point for circle at lat="+lat+" lon="+lon+" cutoffAngle="+cutoffAngle+" planetModel="+planetModel);
|
||||
}
|
||||
final GeoPoint edgePoint = new GeoPoint(newLat, newLon);
|
||||
//if (Math.abs(circlePlane.evaluate(edgePoint)) > 1e-10)
|
||||
// throw new RuntimeException("Computed an edge point that does not satisfy circlePlane equation! "+circlePlane.evaluate(edgePoint));
|
||||
this.edgePoints = new GeoPoint[]{edgePoint};
|
||||
|
@ -92,10 +89,9 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
|||
*/
|
||||
@Override
|
||||
public double computeNormalDistance(final GeoPoint point) {
|
||||
double normalDistance = this.center.normalDistance(point);
|
||||
if (normalDistance > cutoffNormalDistance)
|
||||
if (!isWithin(point))
|
||||
return Double.MAX_VALUE;
|
||||
return normalDistance;
|
||||
return this.center.normalDistance(point);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,10 +101,9 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
|||
*/
|
||||
@Override
|
||||
public double computeNormalDistance(final double x, final double y, final double z) {
|
||||
double normalDistance = this.center.normalDistance(x, y, z);
|
||||
if (normalDistance > cutoffNormalDistance)
|
||||
if (!isWithin(x,y,z))
|
||||
return Double.MAX_VALUE;
|
||||
return normalDistance;
|
||||
return this.center.normalDistance(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -118,10 +113,9 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
|||
*/
|
||||
@Override
|
||||
public double computeSquaredNormalDistance(final GeoPoint point) {
|
||||
double normalDistanceSquared = this.center.normalDistanceSquared(point);
|
||||
if (normalDistanceSquared > cutoffNormalDistance * cutoffNormalDistance)
|
||||
if (!isWithin(point))
|
||||
return Double.MAX_VALUE;
|
||||
return normalDistanceSquared;
|
||||
return this.center.normalDistanceSquared(point);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,10 +125,9 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
|||
*/
|
||||
@Override
|
||||
public double computeSquaredNormalDistance(final double x, final double y, final double z) {
|
||||
double normalDistanceSquared = this.center.normalDistanceSquared(x, y, z);
|
||||
if (normalDistanceSquared > cutoffNormalDistance * cutoffNormalDistance)
|
||||
if (!isWithin(x,y,z))
|
||||
return Double.MAX_VALUE;
|
||||
return normalDistanceSquared;
|
||||
return this.center.normalDistanceSquared(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -143,10 +136,9 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
|||
*/
|
||||
@Override
|
||||
public double computeLinearDistance(final GeoPoint point) {
|
||||
double linearDistance = this.center.linearDistance(point);
|
||||
if (linearDistance > cutoffLinearDistance)
|
||||
if (!isWithin(point))
|
||||
return Double.MAX_VALUE;
|
||||
return linearDistance;
|
||||
return this.center.linearDistance(point);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,10 +147,9 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
|||
*/
|
||||
@Override
|
||||
public double computeLinearDistance(final double x, final double y, final double z) {
|
||||
double linearDistance = this.center.linearDistance(x, y, z);
|
||||
if (linearDistance > cutoffLinearDistance)
|
||||
if (!isWithin(x,y,z))
|
||||
return Double.MAX_VALUE;
|
||||
return linearDistance;
|
||||
return this.center.linearDistance(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -166,10 +157,9 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
|||
*/
|
||||
@Override
|
||||
public double computeSquaredLinearDistance(final GeoPoint point) {
|
||||
double linearDistanceSquared = this.center.linearDistanceSquared(point);
|
||||
if (linearDistanceSquared > cutoffLinearDistance * cutoffLinearDistance)
|
||||
if (!isWithin(point))
|
||||
return Double.MAX_VALUE;
|
||||
return linearDistanceSquared;
|
||||
return this.center.linearDistanceSquared(point);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -177,10 +167,9 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
|||
*/
|
||||
@Override
|
||||
public double computeSquaredLinearDistance(final double x, final double y, final double z) {
|
||||
double linearDistanceSquared = this.center.linearDistanceSquared(x, y, z);
|
||||
if (linearDistanceSquared > cutoffLinearDistance * cutoffLinearDistance)
|
||||
if (!isWithin(x,y,z))
|
||||
return Double.MAX_VALUE;
|
||||
return linearDistanceSquared;
|
||||
return this.center.linearDistanceSquared(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,10 +178,9 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
|||
*/
|
||||
@Override
|
||||
public double computeArcDistance(final GeoPoint point) {
|
||||
double dist = this.center.arcDistance(point);
|
||||
if (dist > cutoffAngle)
|
||||
if (!isWithin(point))
|
||||
return Double.MAX_VALUE;
|
||||
return dist;
|
||||
return this.center.arcDistance(point);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -214,7 +202,7 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
|||
|
||||
@Override
|
||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
return circlePlane.intersects(p, notablePoints, circlePoints, bounds);
|
||||
return circlePlane.intersects(planetModel, p, notablePoints, circlePoints, bounds);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -230,7 +218,7 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
|||
public Bounds getBounds(Bounds bounds) {
|
||||
bounds = super.getBounds(bounds);
|
||||
bounds.addPoint(center);
|
||||
circlePlane.recordBounds(bounds);
|
||||
circlePlane.recordBounds(planetModel, bounds);
|
||||
return bounds;
|
||||
}
|
||||
|
||||
|
@ -239,21 +227,20 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
|||
if (!(o instanceof GeoCircle))
|
||||
return false;
|
||||
GeoCircle other = (GeoCircle) o;
|
||||
return other.center.equals(center) && other.cutoffAngle == cutoffAngle;
|
||||
return super.equals(other) && other.center.equals(center) && other.cutoffAngle == cutoffAngle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result;
|
||||
long temp;
|
||||
result = center.hashCode();
|
||||
temp = Double.doubleToLongBits(cutoffAngle);
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + center.hashCode();
|
||||
long temp = Double.doubleToLongBits(cutoffAngle);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoCircle: {center=" + center + ", radius=" + cutoffAngle + "(" + cutoffAngle * 180.0 / Math.PI + ")}";
|
||||
return "GeoCircle: {planetmodel=" + planetModel+", center=" + center + ", radius=" + cutoffAngle + "(" + cutoffAngle * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,8 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
|||
* Create a convex polygon from a list of points. The first point must be on the
|
||||
* external edge.
|
||||
*/
|
||||
public GeoConvexPolygon(final List<GeoPoint> pointList) {
|
||||
public GeoConvexPolygon(final PlanetModel planetModel, final List<GeoPoint> pointList) {
|
||||
super(planetModel);
|
||||
this.points = pointList;
|
||||
this.isInternalEdges = null;
|
||||
donePoints(false);
|
||||
|
@ -55,7 +56,8 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
|||
* Create a convex polygon from a list of points, keeping track of which boundaries
|
||||
* are internal. This is used when creating a polygon as a building block for another shape.
|
||||
*/
|
||||
public GeoConvexPolygon(final List<GeoPoint> pointList, final BitSet internalEdgeFlags, final boolean returnEdgeInternal) {
|
||||
public GeoConvexPolygon(final PlanetModel planetModel, final List<GeoPoint> pointList, final BitSet internalEdgeFlags, final boolean returnEdgeInternal) {
|
||||
super(planetModel);
|
||||
this.points = pointList;
|
||||
this.isInternalEdges = internalEdgeFlags;
|
||||
donePoints(returnEdgeInternal);
|
||||
|
@ -65,7 +67,8 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
|||
* Create a convex polygon, with a starting latitude and longitude.
|
||||
* Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
|
||||
*/
|
||||
public GeoConvexPolygon(final double startLatitude, final double startLongitude) {
|
||||
public GeoConvexPolygon(final PlanetModel planetModel, final double startLatitude, final double startLongitude) {
|
||||
super(planetModel);
|
||||
points = new ArrayList<GeoPoint>();
|
||||
isInternalEdges = new BitSet();
|
||||
// Argument checking
|
||||
|
@ -74,7 +77,7 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
|||
if (startLongitude < -Math.PI || startLongitude > Math.PI)
|
||||
throw new IllegalArgumentException("Longitude out of range");
|
||||
|
||||
final GeoPoint p = new GeoPoint(startLatitude, startLongitude);
|
||||
final GeoPoint p = new GeoPoint(planetModel, startLatitude, startLongitude);
|
||||
points.add(p);
|
||||
}
|
||||
|
||||
|
@ -94,7 +97,7 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
|||
if (longitude < -Math.PI || longitude > Math.PI)
|
||||
throw new IllegalArgumentException("Longitude out of range");
|
||||
|
||||
final GeoPoint p = new GeoPoint(latitude, longitude);
|
||||
final GeoPoint p = new GeoPoint(planetModel, latitude, longitude);
|
||||
isInternalEdges.set(points.size(), isInternalEdge);
|
||||
points.add(p);
|
||||
}
|
||||
|
@ -191,7 +194,7 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
|||
membershipBounds[count++] = edges[otherIndex];
|
||||
}
|
||||
}
|
||||
if (edge.intersects(p, notablePoints, points, bounds, membershipBounds)) {
|
||||
if (edge.intersects(planetModel, p, notablePoints, points, bounds, membershipBounds)) {
|
||||
//System.err.println(" intersects!");
|
||||
return true;
|
||||
}
|
||||
|
@ -230,7 +233,7 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
|||
membershipBounds[count++] = edges[otherIndex];
|
||||
}
|
||||
}
|
||||
edge.recordBounds(bounds, membershipBounds);
|
||||
edge.recordBounds(planetModel, bounds, membershipBounds);
|
||||
}
|
||||
|
||||
if (fullDistance >= Math.PI) {
|
||||
|
@ -245,6 +248,8 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
|||
if (!(o instanceof GeoConvexPolygon))
|
||||
return false;
|
||||
GeoConvexPolygon other = (GeoConvexPolygon) o;
|
||||
if (!super.equals(other))
|
||||
return false;
|
||||
if (other.points.size() != points.size())
|
||||
return false;
|
||||
|
||||
|
@ -257,17 +262,14 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return points.hashCode();
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + points.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder edgeString = new StringBuilder("{");
|
||||
for (int i = 0; i < edges.length; i++) {
|
||||
edgeString.append(edges[i]).append(" internal? ").append(internalEdges[i]).append("; ");
|
||||
}
|
||||
edgeString.append("}");
|
||||
return "GeoConvexPolygon: {points=" + points + " edges=" + edgeString + "}";
|
||||
return "GeoConvexPolygon: {planetmodel=" + planetModel + ", points=" + points + "}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoDegenerateHorizontalLine extends GeoBBoxBase {
|
||||
public class GeoDegenerateHorizontalLine extends GeoBaseBBox {
|
||||
public final double latitude;
|
||||
public final double leftLon;
|
||||
public final double rightLon;
|
||||
|
@ -44,7 +44,8 @@ public class GeoDegenerateHorizontalLine extends GeoBBoxBase {
|
|||
/**
|
||||
* Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
|
||||
*/
|
||||
public GeoDegenerateHorizontalLine(final double latitude, final double leftLon, double rightLon) {
|
||||
public GeoDegenerateHorizontalLine(final PlanetModel planetModel, final double latitude, final double leftLon, double rightLon) {
|
||||
super(planetModel);
|
||||
// Argument checking
|
||||
if (latitude > Math.PI * 0.5 || latitude < -Math.PI * 0.5)
|
||||
throw new IllegalArgumentException("Latitude out of range");
|
||||
|
@ -71,10 +72,10 @@ public class GeoDegenerateHorizontalLine extends GeoBBoxBase {
|
|||
final double cosRightLon = Math.cos(rightLon);
|
||||
|
||||
// Now build the two points
|
||||
this.LHC = new GeoPoint(sinLatitude, sinLeftLon, cosLatitude, cosLeftLon);
|
||||
this.RHC = new GeoPoint(sinLatitude, sinRightLon, cosLatitude, cosRightLon);
|
||||
this.LHC = new GeoPoint(planetModel, sinLatitude, sinLeftLon, cosLatitude, cosLeftLon);
|
||||
this.RHC = new GeoPoint(planetModel, sinLatitude, sinRightLon, cosLatitude, cosRightLon);
|
||||
|
||||
this.plane = new Plane(sinLatitude);
|
||||
this.plane = new Plane(planetModel, sinLatitude);
|
||||
|
||||
// Normalize
|
||||
while (leftLon > rightLon) {
|
||||
|
@ -84,7 +85,7 @@ public class GeoDegenerateHorizontalLine extends GeoBBoxBase {
|
|||
final double sinMiddleLon = Math.sin(middleLon);
|
||||
final double cosMiddleLon = Math.cos(middleLon);
|
||||
|
||||
this.centerPoint = new GeoPoint(sinLatitude, sinMiddleLon, cosLatitude, cosMiddleLon);
|
||||
this.centerPoint = new GeoPoint(planetModel, sinLatitude, sinMiddleLon, cosLatitude, cosMiddleLon);
|
||||
this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||
|
||||
|
@ -107,7 +108,7 @@ public class GeoDegenerateHorizontalLine extends GeoBBoxBase {
|
|||
newLeftLon = -Math.PI;
|
||||
newRightLon = Math.PI;
|
||||
}
|
||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -148,7 +149,7 @@ public class GeoDegenerateHorizontalLine extends GeoBBoxBase {
|
|||
|
||||
@Override
|
||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
return p.intersects(plane, notablePoints, planePoints, bounds, leftPlane, rightPlane);
|
||||
return p.intersects(planetModel, plane, notablePoints, planePoints, bounds, leftPlane, rightPlane);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -170,12 +171,18 @@ public class GeoDegenerateHorizontalLine extends GeoBBoxBase {
|
|||
|
||||
@Override
|
||||
public int getRelationship(final GeoShape path) {
|
||||
if (path.intersects(plane, planePoints, leftPlane, rightPlane))
|
||||
//System.err.println("getting relationship between "+this+" and "+path);
|
||||
if (path.intersects(plane, planePoints, leftPlane, rightPlane)) {
|
||||
//System.err.println(" overlaps");
|
||||
return OVERLAPS;
|
||||
}
|
||||
|
||||
if (path.isWithin(centerPoint))
|
||||
if (path.isWithin(centerPoint)) {
|
||||
//System.err.println(" contains");
|
||||
return CONTAINS;
|
||||
}
|
||||
|
||||
//System.err.println(" disjoint");
|
||||
return DISJOINT;
|
||||
}
|
||||
|
||||
|
@ -184,19 +191,20 @@ public class GeoDegenerateHorizontalLine extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoDegenerateHorizontalLine))
|
||||
return false;
|
||||
GeoDegenerateHorizontalLine other = (GeoDegenerateHorizontalLine) o;
|
||||
return other.LHC.equals(LHC) && other.RHC.equals(RHC);
|
||||
return super.equals(other) && other.LHC.equals(LHC) && other.RHC.equals(RHC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = LHC.hashCode();
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + LHC.hashCode();
|
||||
result = 31 * result + RHC.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoDegenerateHorizontalLine: {latitude=" + latitude + "(" + latitude * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightLon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
return "GeoDegenerateHorizontalLine: {planetmodel="+planetModel+", latitude=" + latitude + "(" + latitude * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightLon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoDegenerateLatitudeZone extends GeoBBoxBase {
|
||||
public class GeoDegenerateLatitudeZone extends GeoBaseBBox {
|
||||
public final double latitude;
|
||||
|
||||
public final double sinLatitude;
|
||||
|
@ -32,14 +32,15 @@ public class GeoDegenerateLatitudeZone extends GeoBBoxBase {
|
|||
public final GeoPoint[] edgePoints;
|
||||
public final static GeoPoint[] planePoints = new GeoPoint[0];
|
||||
|
||||
public GeoDegenerateLatitudeZone(final double latitude) {
|
||||
public GeoDegenerateLatitudeZone(final PlanetModel planetModel, final double latitude) {
|
||||
super(planetModel);
|
||||
this.latitude = latitude;
|
||||
|
||||
this.sinLatitude = Math.sin(latitude);
|
||||
double cosLatitude = Math.cos(latitude);
|
||||
this.plane = new Plane(sinLatitude);
|
||||
this.plane = new Plane(planetModel, sinLatitude);
|
||||
// Compute an interior point.
|
||||
interiorPoint = new GeoPoint(cosLatitude, 0.0, sinLatitude);
|
||||
interiorPoint = new GeoPoint(planetModel, sinLatitude, 0.0, cosLatitude, 1.0);
|
||||
edgePoints = new GeoPoint[]{interiorPoint};
|
||||
}
|
||||
|
||||
|
@ -47,7 +48,7 @@ public class GeoDegenerateLatitudeZone extends GeoBBoxBase {
|
|||
public GeoBBox expand(final double angle) {
|
||||
double newTopLat = latitude + angle;
|
||||
double newBottomLat = latitude - angle;
|
||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, -Math.PI, Math.PI);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, -Math.PI, Math.PI);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -83,7 +84,7 @@ public class GeoDegenerateLatitudeZone extends GeoBBoxBase {
|
|||
|
||||
@Override
|
||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
return p.intersects(plane, notablePoints, planePoints, bounds);
|
||||
return p.intersects(planetModel, plane, notablePoints, planePoints, bounds);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -125,19 +126,20 @@ public class GeoDegenerateLatitudeZone extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoDegenerateLatitudeZone))
|
||||
return false;
|
||||
GeoDegenerateLatitudeZone other = (GeoDegenerateLatitudeZone) o;
|
||||
return other.latitude == latitude;
|
||||
return super.equals(other) && other.latitude == latitude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
long temp = Double.doubleToLongBits(latitude);
|
||||
int result = (int) (temp ^ (temp >>> 32));
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoDegenerateLatitudeZone: {lat=" + latitude + "(" + latitude * 180.0 / Math.PI + ")}";
|
||||
return "GeoDegenerateLatitudeZone: {planetmodel="+planetModel+", lat=" + latitude + "(" + latitude * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoDegenerateLongitudeSlice extends GeoBBoxBase {
|
||||
public class GeoDegenerateLongitudeSlice extends GeoBaseBBox {
|
||||
public final double longitude;
|
||||
|
||||
public final double sinLongitude;
|
||||
|
@ -32,12 +32,13 @@ public class GeoDegenerateLongitudeSlice extends GeoBBoxBase {
|
|||
public final GeoPoint interiorPoint;
|
||||
public final GeoPoint[] edgePoints;
|
||||
|
||||
public final static GeoPoint[] planePoints = new GeoPoint[]{NORTH_POLE, SOUTH_POLE};
|
||||
public final GeoPoint[] planePoints;
|
||||
|
||||
/**
|
||||
* Accepts only values in the following ranges: lon: {@code -PI -> PI}
|
||||
*/
|
||||
public GeoDegenerateLongitudeSlice(final double longitude) {
|
||||
public GeoDegenerateLongitudeSlice(final PlanetModel planetModel, final double longitude) {
|
||||
super(planetModel);
|
||||
// Argument checking
|
||||
if (longitude < -Math.PI || longitude > Math.PI)
|
||||
throw new IllegalArgumentException("Longitude out of range");
|
||||
|
@ -48,9 +49,10 @@ public class GeoDegenerateLongitudeSlice extends GeoBBoxBase {
|
|||
|
||||
this.plane = new Plane(cosLongitude, sinLongitude);
|
||||
// We need a bounding plane too, which is perpendicular to the longitude plane and sided so that the point (0.0, longitude) is inside.
|
||||
this.interiorPoint = new GeoPoint(cosLongitude, sinLongitude, 0.0);
|
||||
this.interiorPoint = new GeoPoint(planetModel, 0.0, sinLongitude, 1.0, cosLongitude);
|
||||
this.boundingPlane = new SidedPlane(interiorPoint, -sinLongitude, cosLongitude);
|
||||
this.edgePoints = new GeoPoint[]{interiorPoint};
|
||||
this.planePoints = new GeoPoint[]{planetModel.NORTH_POLE, planetModel.SOUTH_POLE};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -63,7 +65,7 @@ public class GeoDegenerateLongitudeSlice extends GeoBBoxBase {
|
|||
newLeftLon = -Math.PI;
|
||||
newRightLon = Math.PI;
|
||||
}
|
||||
return GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, newLeftLon, newRightLon);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, Math.PI * 0.5, -Math.PI * 0.5, newLeftLon, newRightLon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -100,7 +102,7 @@ public class GeoDegenerateLongitudeSlice extends GeoBBoxBase {
|
|||
|
||||
@Override
|
||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
return p.intersects(plane, notablePoints, planePoints, bounds, boundingPlane);
|
||||
return p.intersects(planetModel, plane, notablePoints, planePoints, bounds, boundingPlane);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -138,21 +140,20 @@ public class GeoDegenerateLongitudeSlice extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoDegenerateLongitudeSlice))
|
||||
return false;
|
||||
GeoDegenerateLongitudeSlice other = (GeoDegenerateLongitudeSlice) o;
|
||||
return other.longitude == longitude;
|
||||
return super.equals(other) && other.longitude == longitude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result;
|
||||
long temp;
|
||||
temp = Double.doubleToLongBits(longitude);
|
||||
result = (int) (temp ^ (temp >>> 32));
|
||||
int result = super.hashCode();
|
||||
long temp = Double.doubleToLongBits(longitude);
|
||||
result = result * 31 + (int) (temp ^ (temp >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoDegenerateLongitudeSlice: {longitude=" + longitude + "(" + longitude * 180.0 / Math.PI + ")}";
|
||||
return "GeoDegenerateLongitudeSlice: {planetmodel="+planetModel+", longitude=" + longitude + "(" + longitude * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,10 +26,12 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
public class GeoDegeneratePoint extends GeoPoint implements GeoBBox {
|
||||
public final double latitude;
|
||||
public final double longitude;
|
||||
public final PlanetModel planetModel;
|
||||
public final GeoPoint[] edgePoints;
|
||||
|
||||
public GeoDegeneratePoint(final double lat, final double lon) {
|
||||
super(lat, lon);
|
||||
public GeoDegeneratePoint(final PlanetModel planetModel, final double lat, final double lon) {
|
||||
super(planetModel, lat, lon);
|
||||
this.planetModel = planetModel;
|
||||
this.latitude = lat;
|
||||
this.longitude = lon;
|
||||
this.edgePoints = new GeoPoint[]{this};
|
||||
|
@ -47,7 +49,7 @@ public class GeoDegeneratePoint extends GeoPoint implements GeoBBox {
|
|||
final double newBottomLat = latitude - angle;
|
||||
final double newLeftLon = longitude - angle;
|
||||
final double newRightLon = longitude + angle;
|
||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,15 +110,14 @@ public class GeoDegeneratePoint extends GeoPoint implements GeoBBox {
|
|||
if (!(o instanceof GeoDegeneratePoint))
|
||||
return false;
|
||||
GeoDegeneratePoint other = (GeoDegeneratePoint) o;
|
||||
return other.latitude == latitude && other.longitude == longitude;
|
||||
return super.equals(other) && other.latitude == latitude && other.longitude == longitude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result;
|
||||
long temp;
|
||||
temp = Double.doubleToLongBits(latitude);
|
||||
result = (int) (temp ^ (temp >>> 32));
|
||||
int result = super.hashCode();
|
||||
long temp = Double.doubleToLongBits(latitude);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(longitude);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
return result;
|
||||
|
@ -124,7 +125,7 @@ public class GeoDegeneratePoint extends GeoPoint implements GeoBBox {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoDegeneratePoint: {lat=" + latitude + "(" + latitude * 180.0 / Math.PI + "), lon=" + longitude + "(" + longitude * 180.0 / Math.PI + ")}";
|
||||
return "GeoDegeneratePoint: {planetmodel="+planetModel+", lat=" + latitude + "(" + latitude * 180.0 / Math.PI + "), lon=" + longitude + "(" + longitude * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,7 +22,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoDegenerateVerticalLine extends GeoBBoxBase {
|
||||
public class GeoDegenerateVerticalLine extends GeoBaseBBox {
|
||||
public final double topLat;
|
||||
public final double bottomLat;
|
||||
public final double longitude;
|
||||
|
@ -43,7 +43,8 @@ public class GeoDegenerateVerticalLine extends GeoBBoxBase {
|
|||
/**
|
||||
* Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, longitude: {@code -PI -> PI}
|
||||
*/
|
||||
public GeoDegenerateVerticalLine(final double topLat, final double bottomLat, final double longitude) {
|
||||
public GeoDegenerateVerticalLine(final PlanetModel planetModel, final double topLat, final double bottomLat, final double longitude) {
|
||||
super(planetModel);
|
||||
// Argument checking
|
||||
if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
|
||||
throw new IllegalArgumentException("Top latitude out of range");
|
||||
|
@ -66,8 +67,8 @@ public class GeoDegenerateVerticalLine extends GeoBBoxBase {
|
|||
final double cosLongitude = Math.cos(longitude);
|
||||
|
||||
// Now build the two points
|
||||
this.UHC = new GeoPoint(sinTopLat, sinLongitude, cosTopLat, cosLongitude);
|
||||
this.LHC = new GeoPoint(sinBottomLat, sinLongitude, cosBottomLat, cosLongitude);
|
||||
this.UHC = new GeoPoint(planetModel, sinTopLat, sinLongitude, cosTopLat, cosLongitude);
|
||||
this.LHC = new GeoPoint(planetModel, sinBottomLat, sinLongitude, cosBottomLat, cosLongitude);
|
||||
|
||||
this.plane = new Plane(cosLongitude, sinLongitude);
|
||||
|
||||
|
@ -75,10 +76,10 @@ public class GeoDegenerateVerticalLine extends GeoBBoxBase {
|
|||
final double sinMiddleLat = Math.sin(middleLat);
|
||||
final double cosMiddleLat = Math.cos(middleLat);
|
||||
|
||||
this.centerPoint = new GeoPoint(sinMiddleLat, sinLongitude, cosMiddleLat, cosLongitude);
|
||||
this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinLongitude, cosMiddleLat, cosLongitude);
|
||||
|
||||
this.topPlane = new SidedPlane(centerPoint, sinTopLat);
|
||||
this.bottomPlane = new SidedPlane(centerPoint, sinBottomLat);
|
||||
this.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
|
||||
this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
|
||||
|
||||
this.boundingPlane = new SidedPlane(centerPoint, -sinLongitude, cosLongitude);
|
||||
|
||||
|
@ -98,7 +99,7 @@ public class GeoDegenerateVerticalLine extends GeoBBoxBase {
|
|||
newLeftLon = -Math.PI;
|
||||
newRightLon = Math.PI;
|
||||
}
|
||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -144,7 +145,7 @@ public class GeoDegenerateVerticalLine extends GeoBBoxBase {
|
|||
|
||||
@Override
|
||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
return p.intersects(plane, notablePoints, planePoints, bounds, boundingPlane, topPlane, bottomPlane);
|
||||
return p.intersects(planetModel, plane, notablePoints, planePoints, bounds, boundingPlane, topPlane, bottomPlane);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,12 +188,13 @@ public class GeoDegenerateVerticalLine extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoDegenerateVerticalLine))
|
||||
return false;
|
||||
GeoDegenerateVerticalLine other = (GeoDegenerateVerticalLine) o;
|
||||
return other.UHC.equals(UHC) && other.LHC.equals(LHC);
|
||||
return super.equals(other) && other.UHC.equals(UHC) && other.LHC.equals(LHC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = UHC.hashCode();
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + UHC.hashCode();
|
||||
result = 31 * result + LHC.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoLatitudeZone extends GeoBBoxBase {
|
||||
public class GeoLatitudeZone extends GeoBaseBBox {
|
||||
public final double topLat;
|
||||
public final double bottomLat;
|
||||
public final double cosTopLat;
|
||||
|
@ -40,7 +40,8 @@ public class GeoLatitudeZone extends GeoBBoxBase {
|
|||
// Edge points
|
||||
public final GeoPoint[] edgePoints;
|
||||
|
||||
public GeoLatitudeZone(final double topLat, final double bottomLat) {
|
||||
public GeoLatitudeZone(final PlanetModel planetModel, final double topLat, final double bottomLat) {
|
||||
super(planetModel);
|
||||
this.topLat = topLat;
|
||||
this.bottomLat = bottomLat;
|
||||
|
||||
|
@ -49,19 +50,15 @@ public class GeoLatitudeZone extends GeoBBoxBase {
|
|||
this.cosTopLat = Math.cos(topLat);
|
||||
this.cosBottomLat = Math.cos(bottomLat);
|
||||
|
||||
// Construct sample points, so we get our sidedness right
|
||||
final Vector topPoint = new Vector(0.0, 0.0, sinTopLat);
|
||||
final Vector bottomPoint = new Vector(0.0, 0.0, sinBottomLat);
|
||||
|
||||
// Compute an interior point. Pick one whose lat is between top and bottom.
|
||||
final double middleLat = (topLat + bottomLat) * 0.5;
|
||||
final double sinMiddleLat = Math.sin(middleLat);
|
||||
this.interiorPoint = new GeoPoint(Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 0.0, sinMiddleLat);
|
||||
this.topBoundaryPoint = new GeoPoint(Math.sqrt(1.0 - sinTopLat * sinTopLat), 0.0, sinTopLat);
|
||||
this.bottomBoundaryPoint = new GeoPoint(Math.sqrt(1.0 - sinBottomLat * sinBottomLat), 0.0, sinBottomLat);
|
||||
this.interiorPoint = new GeoPoint(planetModel, sinMiddleLat, 0.0, Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 1.0);
|
||||
this.topBoundaryPoint = new GeoPoint(planetModel, sinTopLat, 0.0, Math.sqrt(1.0 - sinTopLat * sinTopLat), 1.0);
|
||||
this.bottomBoundaryPoint = new GeoPoint(planetModel, sinBottomLat, 0.0, Math.sqrt(1.0 - sinBottomLat * sinBottomLat), 1.0);
|
||||
|
||||
this.topPlane = new SidedPlane(interiorPoint, sinTopLat);
|
||||
this.bottomPlane = new SidedPlane(interiorPoint, sinBottomLat);
|
||||
this.topPlane = new SidedPlane(interiorPoint, planetModel, sinTopLat);
|
||||
this.bottomPlane = new SidedPlane(interiorPoint, planetModel, sinBottomLat);
|
||||
|
||||
this.edgePoints = new GeoPoint[]{topBoundaryPoint, bottomBoundaryPoint};
|
||||
}
|
||||
|
@ -70,7 +67,7 @@ public class GeoLatitudeZone extends GeoBBoxBase {
|
|||
public GeoBBox expand(final double angle) {
|
||||
final double newTopLat = topLat + angle;
|
||||
final double newBottomLat = bottomLat - angle;
|
||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, -Math.PI, Math.PI);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, -Math.PI, Math.PI);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -115,8 +112,8 @@ public class GeoLatitudeZone extends GeoBBoxBase {
|
|||
|
||||
@Override
|
||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
return p.intersects(topPlane, notablePoints, planePoints, bounds, bottomPlane) ||
|
||||
p.intersects(bottomPlane, notablePoints, planePoints, bounds, topPlane);
|
||||
return p.intersects(planetModel, topPlane, notablePoints, planePoints, bounds, bottomPlane) ||
|
||||
p.intersects(planetModel, bottomPlane, notablePoints, planePoints, bounds, topPlane);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -181,18 +178,19 @@ public class GeoLatitudeZone extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoLatitudeZone))
|
||||
return false;
|
||||
GeoLatitudeZone other = (GeoLatitudeZone) o;
|
||||
return other.topPlane.equals(topPlane) && other.bottomPlane.equals(bottomPlane);
|
||||
return super.equals(other) && other.topBoundaryPoint.equals(topBoundaryPoint) && other.bottomBoundaryPoint.equals(bottomBoundaryPoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = topPlane.hashCode();
|
||||
result = 31 * result + bottomPlane.hashCode();
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + topBoundaryPoint.hashCode();
|
||||
result = 31 * result + bottomBoundaryPoint.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoLatitudeZone: {toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + ")}";
|
||||
return "GeoLatitudeZone: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,23 +24,24 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoLongitudeSlice extends GeoBBoxBase {
|
||||
public class GeoLongitudeSlice extends GeoBaseBBox {
|
||||
public final double leftLon;
|
||||
public final double rightLon;
|
||||
|
||||
public final SidedPlane leftPlane;
|
||||
public final SidedPlane rightPlane;
|
||||
|
||||
public final static GeoPoint[] planePoints = new GeoPoint[]{NORTH_POLE, SOUTH_POLE};
|
||||
public final GeoPoint[] planePoints;
|
||||
|
||||
public final GeoPoint centerPoint;
|
||||
|
||||
public final static GeoPoint[] edgePoints = new GeoPoint[]{NORTH_POLE};
|
||||
public final GeoPoint[] edgePoints;
|
||||
|
||||
/**
|
||||
* Accepts only values in the following ranges: lon: {@code -PI -> PI}
|
||||
*/
|
||||
public GeoLongitudeSlice(final double leftLon, double rightLon) {
|
||||
public GeoLongitudeSlice(final PlanetModel planetModel, final double leftLon, double rightLon) {
|
||||
super(planetModel);
|
||||
// Argument checking
|
||||
if (leftLon < -Math.PI || leftLon > Math.PI)
|
||||
throw new IllegalArgumentException("Left longitude out of range");
|
||||
|
@ -66,11 +67,13 @@ public class GeoLongitudeSlice extends GeoBBoxBase {
|
|||
rightLon += Math.PI * 2.0;
|
||||
}
|
||||
final double middleLon = (leftLon + rightLon) * 0.5;
|
||||
this.centerPoint = new GeoPoint(0.0, middleLon);
|
||||
this.centerPoint = new GeoPoint(planetModel, 0.0, middleLon);
|
||||
|
||||
this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||
|
||||
this.planePoints = new GeoPoint[]{planetModel.NORTH_POLE, planetModel.SOUTH_POLE};
|
||||
this.edgePoints = new GeoPoint[]{planetModel.NORTH_POLE};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -85,7 +88,7 @@ public class GeoLongitudeSlice extends GeoBBoxBase {
|
|||
newLeftLon = -Math.PI;
|
||||
newRightLon = Math.PI;
|
||||
}
|
||||
return GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, newLeftLon, newRightLon);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, Math.PI * 0.5, -Math.PI * 0.5, newLeftLon, newRightLon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -126,8 +129,8 @@ public class GeoLongitudeSlice extends GeoBBoxBase {
|
|||
|
||||
@Override
|
||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
return p.intersects(leftPlane, notablePoints, planePoints, bounds, rightPlane) ||
|
||||
p.intersects(rightPlane, notablePoints, planePoints, bounds, leftPlane);
|
||||
return p.intersects(planetModel, leftPlane, notablePoints, planePoints, bounds, rightPlane) ||
|
||||
p.intersects(planetModel, rightPlane, notablePoints, planePoints, bounds, leftPlane);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -154,7 +157,7 @@ public class GeoLongitudeSlice extends GeoBBoxBase {
|
|||
if (insideRectangle == SOME_INSIDE)
|
||||
return OVERLAPS;
|
||||
|
||||
final boolean insideShape = path.isWithin(NORTH_POLE);
|
||||
final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
|
||||
|
||||
if (insideRectangle == ALL_INSIDE && insideShape)
|
||||
return OVERLAPS;
|
||||
|
@ -180,15 +183,14 @@ public class GeoLongitudeSlice extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoLongitudeSlice))
|
||||
return false;
|
||||
GeoLongitudeSlice other = (GeoLongitudeSlice) o;
|
||||
return other.leftLon == leftLon && other.rightLon == rightLon;
|
||||
return super.equals(other) && other.leftLon == leftLon && other.rightLon == rightLon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result;
|
||||
long temp;
|
||||
temp = Double.doubleToLongBits(leftLon);
|
||||
result = (int) (temp ^ (temp >>> 32));
|
||||
int result = super.hashCode();
|
||||
long temp = Double.doubleToLongBits(leftLon);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(rightLon);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
return result;
|
||||
|
@ -196,7 +198,7 @@ public class GeoLongitudeSlice extends GeoBBoxBase {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoLongitudeSlice: {leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
return "GeoLongitudeSlice: {planetmodel="+planetModel+", leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoNorthLatitudeZone extends GeoBBoxBase {
|
||||
public class GeoNorthLatitudeZone extends GeoBaseBBox {
|
||||
public final double bottomLat;
|
||||
public final double cosBottomLat;
|
||||
public final SidedPlane bottomPlane;
|
||||
|
@ -34,22 +34,20 @@ public class GeoNorthLatitudeZone extends GeoBBoxBase {
|
|||
// Edge points
|
||||
public final GeoPoint[] edgePoints;
|
||||
|
||||
public GeoNorthLatitudeZone(final double bottomLat) {
|
||||
public GeoNorthLatitudeZone(final PlanetModel planetModel, final double bottomLat) {
|
||||
super(planetModel);
|
||||
this.bottomLat = bottomLat;
|
||||
|
||||
final double sinBottomLat = Math.sin(bottomLat);
|
||||
this.cosBottomLat = Math.cos(bottomLat);
|
||||
|
||||
// Construct sample points, so we get our sidedness right
|
||||
final Vector bottomPoint = new Vector(0.0, 0.0, sinBottomLat);
|
||||
|
||||
// Compute an interior point. Pick one whose lat is between top and bottom.
|
||||
final double middleLat = (Math.PI * 0.5 + bottomLat) * 0.5;
|
||||
final double sinMiddleLat = Math.sin(middleLat);
|
||||
this.interiorPoint = new GeoPoint(Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 0.0, sinMiddleLat);
|
||||
this.bottomBoundaryPoint = new GeoPoint(Math.sqrt(1.0 - sinBottomLat * sinBottomLat), 0.0, sinBottomLat);
|
||||
this.interiorPoint = new GeoPoint(planetModel, sinMiddleLat, 0.0, Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 1.0);
|
||||
this.bottomBoundaryPoint = new GeoPoint(planetModel, sinBottomLat, 0.0, Math.sqrt(1.0 - sinBottomLat * sinBottomLat), 1.0);
|
||||
|
||||
this.bottomPlane = new SidedPlane(interiorPoint, sinBottomLat);
|
||||
this.bottomPlane = new SidedPlane(interiorPoint, planetModel, sinBottomLat);
|
||||
|
||||
this.edgePoints = new GeoPoint[]{bottomBoundaryPoint};
|
||||
}
|
||||
|
@ -58,7 +56,7 @@ public class GeoNorthLatitudeZone extends GeoBBoxBase {
|
|||
public GeoBBox expand(final double angle) {
|
||||
final double newTopLat = Math.PI * 0.5;
|
||||
final double newBottomLat = bottomLat - angle;
|
||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, -Math.PI, Math.PI);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, -Math.PI, Math.PI);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -101,7 +99,7 @@ public class GeoNorthLatitudeZone extends GeoBBoxBase {
|
|||
@Override
|
||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
return
|
||||
p.intersects(bottomPlane, notablePoints, planePoints, bounds);
|
||||
p.intersects(planetModel, bottomPlane, notablePoints, planePoints, bounds);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,18 +157,19 @@ public class GeoNorthLatitudeZone extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoNorthLatitudeZone))
|
||||
return false;
|
||||
GeoNorthLatitudeZone other = (GeoNorthLatitudeZone) o;
|
||||
return other.bottomPlane.equals(bottomPlane);
|
||||
return super.equals(other) && other.bottomBoundaryPoint.equals(bottomBoundaryPoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = bottomPlane.hashCode();
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + bottomBoundaryPoint.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoNorthLatitudeZone: {bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + ")}";
|
||||
return "GeoNorthLatitudeZone: {planetmodel="+planetModel+", bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoNorthRectangle extends GeoBBoxBase {
|
||||
public class GeoNorthRectangle extends GeoBaseBBox {
|
||||
public final double bottomLat;
|
||||
public final double leftLon;
|
||||
public final double rightLon;
|
||||
|
@ -45,12 +45,13 @@ public class GeoNorthRectangle extends GeoBBoxBase {
|
|||
|
||||
public final GeoPoint centerPoint;
|
||||
|
||||
public final GeoPoint[] edgePoints = new GeoPoint[]{NORTH_POLE};
|
||||
public final GeoPoint[] edgePoints;
|
||||
|
||||
/**
|
||||
* Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
|
||||
*/
|
||||
public GeoNorthRectangle(final double bottomLat, final double leftLon, double rightLon) {
|
||||
public GeoNorthRectangle(final PlanetModel planetModel, final double bottomLat, final double leftLon, double rightLon) {
|
||||
super(planetModel);
|
||||
// Argument checking
|
||||
if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
|
||||
throw new IllegalArgumentException("Bottom latitude out of range");
|
||||
|
@ -77,8 +78,8 @@ public class GeoNorthRectangle extends GeoBBoxBase {
|
|||
final double cosRightLon = Math.cos(rightLon);
|
||||
|
||||
// Now build the points
|
||||
this.LRHC = new GeoPoint(sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
|
||||
this.LLHC = new GeoPoint(sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
|
||||
this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
|
||||
this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
|
||||
|
||||
final double middleLat = (Math.PI * 0.5 + bottomLat) * 0.5;
|
||||
final double sinMiddleLat = Math.sin(middleLat);
|
||||
|
@ -91,16 +92,17 @@ public class GeoNorthRectangle extends GeoBBoxBase {
|
|||
final double sinMiddleLon = Math.sin(middleLon);
|
||||
final double cosMiddleLon = Math.cos(middleLon);
|
||||
|
||||
this.centerPoint = new GeoPoint(sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
|
||||
this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
|
||||
|
||||
this.bottomPlane = new SidedPlane(centerPoint, sinBottomLat);
|
||||
this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
|
||||
this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||
|
||||
this.bottomPlanePoints = new GeoPoint[]{LLHC, LRHC};
|
||||
this.leftPlanePoints = new GeoPoint[]{NORTH_POLE, LLHC};
|
||||
this.rightPlanePoints = new GeoPoint[]{NORTH_POLE, LRHC};
|
||||
this.leftPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LLHC};
|
||||
this.rightPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LRHC};
|
||||
|
||||
this.edgePoints = new GeoPoint[]{planetModel.NORTH_POLE};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -117,7 +119,7 @@ public class GeoNorthRectangle extends GeoBBoxBase {
|
|||
newLeftLon = -Math.PI;
|
||||
newRightLon = Math.PI;
|
||||
}
|
||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -164,9 +166,9 @@ public class GeoNorthRectangle extends GeoBBoxBase {
|
|||
@Override
|
||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
return
|
||||
p.intersects(bottomPlane, notablePoints, bottomPlanePoints, bounds, leftPlane, rightPlane) ||
|
||||
p.intersects(leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, bottomPlane) ||
|
||||
p.intersects(rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, bottomPlane);
|
||||
p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, leftPlane, rightPlane) ||
|
||||
p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, bottomPlane) ||
|
||||
p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, bottomPlane);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -196,7 +198,7 @@ public class GeoNorthRectangle extends GeoBBoxBase {
|
|||
return OVERLAPS;
|
||||
}
|
||||
|
||||
final boolean insideShape = path.isWithin(NORTH_POLE);
|
||||
final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
|
||||
|
||||
if (insideRectangle == ALL_INSIDE && insideShape) {
|
||||
//System.err.println(" inside of each other");
|
||||
|
@ -229,19 +231,20 @@ public class GeoNorthRectangle extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoNorthRectangle))
|
||||
return false;
|
||||
GeoNorthRectangle other = (GeoNorthRectangle) o;
|
||||
return other.LLHC.equals(LLHC) && other.LRHC.equals(LRHC);
|
||||
return super.equals(other) && other.LLHC.equals(LLHC) && other.LRHC.equals(LRHC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = LLHC.hashCode();
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + LLHC.hashCode();
|
||||
result = 31 * result + LRHC.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoNorthRectangle: {bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
return "GeoNorthRectangle: {planetmodel="+planetModel+", bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,29 +29,25 @@ import java.util.List;
|
|||
* @lucene.experimental
|
||||
*/
|
||||
public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
||||
|
||||
public final double cutoffAngle;
|
||||
public final double cutoffOffset;
|
||||
public final double originDistance;
|
||||
public final double chordDistance;
|
||||
public final double sinAngle;
|
||||
public final double cosAngle;
|
||||
|
||||
public final List<SegmentEndpoint> points = new ArrayList<SegmentEndpoint>();
|
||||
public final List<GeoPoint> points = new ArrayList<GeoPoint>();
|
||||
|
||||
public final List<SegmentEndpoint> endPoints = new ArrayList<SegmentEndpoint>();
|
||||
public final List<PathSegment> segments = new ArrayList<PathSegment>();
|
||||
|
||||
public GeoPoint[] edgePoints = null;
|
||||
|
||||
public GeoPath(final double cutoffAngle) {
|
||||
super();
|
||||
if (cutoffAngle <= 0.0 || cutoffAngle > Math.PI * 0.5)
|
||||
public GeoPath(final PlanetModel planetModel, final double maxCutoffAngle) {
|
||||
super(planetModel);
|
||||
if (maxCutoffAngle <= 0.0 || maxCutoffAngle > Math.PI * 0.5)
|
||||
throw new IllegalArgumentException("Cutoff angle out of bounds");
|
||||
this.cutoffAngle = cutoffAngle;
|
||||
final double cosAngle = Math.cos(cutoffAngle);
|
||||
final double sinAngle = Math.sin(cutoffAngle);
|
||||
// Cutoff offset is the linear distance given the angle
|
||||
this.cutoffOffset = sinAngle;
|
||||
this.originDistance = cosAngle;
|
||||
// Compute chord distance
|
||||
double xDiff = 1.0 - cosAngle;
|
||||
this.chordDistance = Math.sqrt(xDiff * xDiff + sinAngle * sinAngle);
|
||||
this.cutoffAngle = maxCutoffAngle;
|
||||
this.cosAngle = Math.cos(maxCutoffAngle);
|
||||
this.sinAngle = Math.sin(maxCutoffAngle);
|
||||
}
|
||||
|
||||
public void addPoint(double lat, double lon) {
|
||||
|
@ -59,57 +55,80 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
|||
throw new IllegalArgumentException("Latitude out of range");
|
||||
if (lon < -Math.PI || lon > Math.PI)
|
||||
throw new IllegalArgumentException("Longitude out of range");
|
||||
final GeoPoint end = new GeoPoint(lat, lon);
|
||||
if (points.size() > 0) {
|
||||
final GeoPoint start = points.get(points.size() - 1).point;
|
||||
final PathSegment ps = new PathSegment(start, end, cutoffOffset, cutoffAngle, chordDistance);
|
||||
// Check for degeneracy; if the segment is degenerate, don't include the point
|
||||
if (ps.isDegenerate())
|
||||
return;
|
||||
segments.add(ps);
|
||||
} else {
|
||||
// First point. We compute the basic set of edgepoints here because we've got the lat and lon available.
|
||||
// Move from center only in latitude. Then, if we go past the north pole, adjust the longitude also.
|
||||
double newLat = lat + cutoffAngle;
|
||||
double newLon = lon;
|
||||
if (newLat > Math.PI * 0.5) {
|
||||
newLat = Math.PI - newLat;
|
||||
newLon += Math.PI;
|
||||
}
|
||||
while (newLon > Math.PI) {
|
||||
newLon -= Math.PI * 2.0;
|
||||
}
|
||||
final GeoPoint edgePoint = new GeoPoint(newLat, newLon);
|
||||
this.edgePoints = new GeoPoint[]{edgePoint};
|
||||
}
|
||||
final SegmentEndpoint se = new SegmentEndpoint(end, originDistance, cutoffOffset, cutoffAngle, chordDistance);
|
||||
points.add(se);
|
||||
points.add(new GeoPoint(planetModel, lat, lon));
|
||||
}
|
||||
|
||||
|
||||
public void done() {
|
||||
if (points.size() == 0)
|
||||
throw new IllegalArgumentException("Path must have at least one point");
|
||||
if (segments.size() > 0) {
|
||||
edgePoints = new GeoPoint[]{points.get(0).circlePlane.getSampleIntersectionPoint(segments.get(0).invertedStartCutoffPlane)};
|
||||
}
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
final SegmentEndpoint pathPoint = points.get(i);
|
||||
Membership previousEndBound = null;
|
||||
GeoPoint[] previousEndNotablePoints = null;
|
||||
Membership nextStartBound = null;
|
||||
GeoPoint[] nextStartNotablePoints = null;
|
||||
if (i > 0) {
|
||||
final PathSegment previousSegment = segments.get(i - 1);
|
||||
previousEndBound = previousSegment.invertedEndCutoffPlane;
|
||||
previousEndNotablePoints = previousSegment.endCutoffPlanePoints;
|
||||
// Compute an offset to use for all segments. This will be based on the minimum magnitude of
|
||||
// the entire ellipsoid.
|
||||
final double cutoffOffset = this.sinAngle * planetModel.getMinimumMagnitude();
|
||||
|
||||
// First, build all segments. We'll then go back and build corresponding segment endpoints.
|
||||
GeoPoint lastPoint = null;
|
||||
for (final GeoPoint end : points) {
|
||||
if (lastPoint != null) {
|
||||
final Plane normalizedConnectingPlane = new Plane(lastPoint, end).normalize();
|
||||
if (normalizedConnectingPlane == null) {
|
||||
continue;
|
||||
}
|
||||
segments.add(new PathSegment(planetModel, lastPoint, end, normalizedConnectingPlane, cutoffOffset));
|
||||
}
|
||||
if (i < segments.size()) {
|
||||
final PathSegment nextSegment = segments.get(i);
|
||||
nextStartBound = nextSegment.invertedStartCutoffPlane;
|
||||
nextStartNotablePoints = nextSegment.startCutoffPlanePoints;
|
||||
}
|
||||
pathPoint.setCutoffPlanes(previousEndNotablePoints, previousEndBound, nextStartNotablePoints, nextStartBound);
|
||||
lastPoint = end;
|
||||
}
|
||||
|
||||
if (segments.size() == 0) {
|
||||
// Simple circle
|
||||
final SegmentEndpoint onlyEndpoint = new SegmentEndpoint(points.get(0), cutoffOffset);
|
||||
endPoints.add(onlyEndpoint);
|
||||
// Find an edgepoint
|
||||
// We already have circle plane, which is the definitive determination of the edge of the "circle".
|
||||
// Next, compute vertical plane going through origin and the center point (C = 0, D = 0).
|
||||
Plane verticalPlane = Plane.constructNormalizedVerticalPlane(onlyEndpoint.point.x, onlyEndpoint.point.y);
|
||||
if (verticalPlane == null) {
|
||||
verticalPlane = new Plane(1.0,0.0);
|
||||
}
|
||||
// Finally, use Plane.findIntersections() to find the intersection points.
|
||||
final GeoPoint edgePoint = onlyEndpoint.circlePlane.getSampleIntersectionPoint(planetModel, verticalPlane);
|
||||
if (edgePoint == null) {
|
||||
throw new RuntimeException("Could not find edge point for path endpoint="+onlyEndpoint.point+" cutoffOffset="+cutoffOffset+" planetModel="+planetModel);
|
||||
}
|
||||
this.edgePoints = new GeoPoint[]{edgePoint};
|
||||
return;
|
||||
}
|
||||
|
||||
// Create segment endpoints. Use an appropriate constructor for the start and end of the path.
|
||||
for (int i = 0; i < segments.size(); i++) {
|
||||
final PathSegment currentSegment = segments.get(i);
|
||||
|
||||
if (i == 0) {
|
||||
// Starting endpoint
|
||||
final SegmentEndpoint startEndpoint = new SegmentEndpoint(currentSegment.start,
|
||||
currentSegment.startCutoffPlane, currentSegment.ULHC, currentSegment.LLHC);
|
||||
endPoints.add(startEndpoint);
|
||||
this.edgePoints = new GeoPoint[]{currentSegment.ULHC};
|
||||
continue;
|
||||
}
|
||||
|
||||
// General intersection case
|
||||
final PathSegment prevSegment = segments.get(i-1);
|
||||
if (prevSegment.upperConnectingPlane.isNumericallyIdentical(currentSegment.upperConnectingPlane) &&
|
||||
prevSegment.lowerConnectingPlane.isNumericallyIdentical(currentSegment.lowerConnectingPlane)) {
|
||||
// The planes are identical. We don't need a circle at all. Special constructor...
|
||||
endPoints.add(new SegmentEndpoint(currentSegment.start));
|
||||
} else {
|
||||
endPoints.add(new SegmentEndpoint(currentSegment.start,
|
||||
prevSegment.endCutoffPlane, currentSegment.startCutoffPlane,
|
||||
prevSegment.URHC, prevSegment.LRHC,
|
||||
currentSegment.ULHC, currentSegment.LLHC));
|
||||
}
|
||||
}
|
||||
// Do final endpoint
|
||||
final PathSegment lastSegment = segments.get(segments.size()-1);
|
||||
endPoints.add(new SegmentEndpoint(lastSegment.end,
|
||||
lastSegment.endCutoffPlane, lastSegment.URHC, lastSegment.LRHC));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,7 +151,7 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
|||
|
||||
int segmentIndex = 0;
|
||||
currentDistance = 0.0;
|
||||
for (SegmentEndpoint endpoint : points) {
|
||||
for (SegmentEndpoint endpoint : endPoints) {
|
||||
double distance = endpoint.pathNormalDistance(point);
|
||||
if (distance != Double.MAX_VALUE)
|
||||
return currentDistance + distance;
|
||||
|
@ -194,7 +213,7 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
|||
|
||||
int segmentIndex = 0;
|
||||
currentDistance = 0.0;
|
||||
for (SegmentEndpoint endpoint : points) {
|
||||
for (SegmentEndpoint endpoint : endPoints) {
|
||||
double distance = endpoint.pathLinearDistance(point);
|
||||
if (distance != Double.MAX_VALUE)
|
||||
return currentDistance + distance;
|
||||
|
@ -251,7 +270,7 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
|||
|
||||
int segmentIndex = 0;
|
||||
currentDistance = 0.0;
|
||||
for (SegmentEndpoint endpoint : points) {
|
||||
for (SegmentEndpoint endpoint : endPoints) {
|
||||
double distance = endpoint.pathDistance(point);
|
||||
if (distance != Double.MAX_VALUE)
|
||||
return currentDistance + distance;
|
||||
|
@ -264,20 +283,26 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
|||
|
||||
@Override
|
||||
public boolean isWithin(final Vector point) {
|
||||
for (SegmentEndpoint pathPoint : points) {
|
||||
if (pathPoint.isWithin(point))
|
||||
//System.err.println("Assessing whether point "+point+" is within geopath "+this);
|
||||
for (SegmentEndpoint pathPoint : endPoints) {
|
||||
if (pathPoint.isWithin(point)) {
|
||||
//System.err.println(" point is within SegmentEndpoint "+pathPoint);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (PathSegment pathSegment : segments) {
|
||||
if (pathSegment.isWithin(point))
|
||||
if (pathSegment.isWithin(point)) {
|
||||
//System.err.println(" point is within PathSegment "+pathSegment);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//System.err.println(" point is not within geopath");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWithin(final double x, final double y, final double z) {
|
||||
for (SegmentEndpoint pathPoint : points) {
|
||||
for (SegmentEndpoint pathPoint : endPoints) {
|
||||
if (pathPoint.isWithin(x, y, z))
|
||||
return true;
|
||||
}
|
||||
|
@ -304,15 +329,15 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
|||
// any of the intersection points are within the bounds, then we've detected an intersection.
|
||||
// Well, sort of. We can detect intersections also due to overlap of segments with each other.
|
||||
// But that's an edge case and we won't be optimizing for it.
|
||||
|
||||
for (final SegmentEndpoint pathPoint : points) {
|
||||
if (pathPoint.intersects(plane, notablePoints, bounds)) {
|
||||
//System.err.println(" Looking for intersection of plane "+plane+" with path "+this);
|
||||
for (final SegmentEndpoint pathPoint : endPoints) {
|
||||
if (pathPoint.intersects(planetModel, plane, notablePoints, bounds)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (final PathSegment pathSegment : segments) {
|
||||
if (pathSegment.intersects(plane, notablePoints, bounds)) {
|
||||
if (pathSegment.intersects(planetModel, plane, notablePoints, bounds)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -336,10 +361,10 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
|||
// never more than 180 degrees longitude at a pop or we risk having the
|
||||
// bounds object get itself inverted. So do the edges first.
|
||||
for (PathSegment pathSegment : segments) {
|
||||
pathSegment.getBounds(bounds);
|
||||
pathSegment.getBounds(planetModel, bounds);
|
||||
}
|
||||
for (SegmentEndpoint pathPoint : points) {
|
||||
pathPoint.getBounds(bounds);
|
||||
for (SegmentEndpoint pathPoint : endPoints) {
|
||||
pathPoint.getBounds(planetModel, bounds);
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
@ -349,13 +374,15 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
|||
if (!(o instanceof GeoPath))
|
||||
return false;
|
||||
GeoPath p = (GeoPath) o;
|
||||
if (points.size() != p.points.size())
|
||||
if (!super.equals(p))
|
||||
return false;
|
||||
if (endPoints.size() != p.endPoints.size())
|
||||
return false;
|
||||
if (cutoffAngle != p.cutoffAngle)
|
||||
return false;
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
SegmentEndpoint point = points.get(i);
|
||||
SegmentEndpoint point2 = p.points.get(i);
|
||||
for (int i = 0; i < endPoints.size(); i++) {
|
||||
SegmentEndpoint point = endPoints.get(i);
|
||||
SegmentEndpoint point2 = p.endPoints.get(i);
|
||||
if (!point.equals(point2))
|
||||
return false;
|
||||
}
|
||||
|
@ -364,101 +391,168 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result;
|
||||
long temp;
|
||||
temp = Double.doubleToLongBits(cutoffAngle);
|
||||
result = (int) (temp ^ (temp >>> 32));
|
||||
result = 31 * result + points.hashCode();
|
||||
int result = super.hashCode();
|
||||
long temp = Double.doubleToLongBits(cutoffAngle);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
result = 31 * result + endPoints.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoPath: {width=" + cutoffAngle + "(" + cutoffAngle * 180.0 / Math.PI + "), points={" + points + "}}";
|
||||
return "GeoPath: {planetmodel=" + planetModel+", width=" + cutoffAngle + "(" + cutoffAngle * 180.0 / Math.PI + "), points={" + points + "}}";
|
||||
}
|
||||
|
||||
/**
|
||||
* This is precalculated data for segment endpoint.
|
||||
* Note well: This is not necessarily a circle. There are four cases:
|
||||
* (1) The path consists of a single endpoint. In this case, we build a simple circle with the proper cutoff offset.
|
||||
* (2) This is the end of a path. The circle plane must be constructed to go through two supplied points and be perpendicular to a connecting plane.
|
||||
* (3) This is an intersection in a path. We are supplied FOUR planes. If there are intersections within bounds for both upper and lower, then
|
||||
* we generate no circle at all. If there is one intersection only, then we generate a plane that includes that intersection, as well as the remaining
|
||||
* cutoff plane/edge plane points.
|
||||
*/
|
||||
public static class SegmentEndpoint {
|
||||
public final GeoPoint point;
|
||||
public final SidedPlane circlePlane;
|
||||
public final double cutoffNormalDistance;
|
||||
public final double cutoffAngle;
|
||||
public final double chordDistance;
|
||||
public Membership[] cutoffPlanes = null;
|
||||
public GeoPoint[] notablePoints = null;
|
||||
public final Membership[] cutoffPlanes;
|
||||
public final GeoPoint[] notablePoints;
|
||||
|
||||
public final static GeoPoint[] circlePoints = new GeoPoint[0];
|
||||
|
||||
public SegmentEndpoint(final GeoPoint point, final double originDistance, final double cutoffOffset, final double cutoffAngle, final double chordDistance) {
|
||||
/** Base case. Does nothing at all.
|
||||
*/
|
||||
public SegmentEndpoint(final GeoPoint point) {
|
||||
this.point = point;
|
||||
this.cutoffNormalDistance = cutoffOffset;
|
||||
this.cutoffAngle = cutoffAngle;
|
||||
this.chordDistance = chordDistance;
|
||||
this.circlePlane = new SidedPlane(point, point, -originDistance);
|
||||
this.circlePlane = null;
|
||||
this.cutoffPlanes = null;
|
||||
this.notablePoints = null;
|
||||
}
|
||||
|
||||
/** Constructor for case (1).
|
||||
* Generate a simple circle cutoff plane.
|
||||
*/
|
||||
public SegmentEndpoint(final GeoPoint point, final double cutoffOffset) {
|
||||
this.point = point;
|
||||
final double magnitude = point.magnitude();
|
||||
// Normalize vector to make D value correct
|
||||
this.circlePlane = new SidedPlane(point, point.normalize(), -Math.sqrt(magnitude * magnitude - cutoffOffset * cutoffOffset));
|
||||
this.cutoffPlanes = new Membership[0];
|
||||
this.notablePoints = new GeoPoint[0];
|
||||
}
|
||||
|
||||
/** Constructor for case (2).
|
||||
* Generate an endpoint, given a single cutoff plane plus upper and lower edge points.
|
||||
*/
|
||||
public SegmentEndpoint(final GeoPoint point,
|
||||
final SidedPlane cutoffPlane, final GeoPoint topEdgePoint, final GeoPoint bottomEdgePoint) {
|
||||
this.point = point;
|
||||
this.cutoffPlanes = new Membership[]{new SidedPlane(cutoffPlane)};
|
||||
this.notablePoints = new GeoPoint[]{topEdgePoint, bottomEdgePoint};
|
||||
// To construct the plane, we now just need D, which is simply the negative of the evaluation of the circle normal vector at one of the points.
|
||||
this.circlePlane = SidedPlane.constructNormalizedPerpendicularSidedPlane(point, cutoffPlane, topEdgePoint, bottomEdgePoint);
|
||||
}
|
||||
|
||||
/** Constructor for case (3).
|
||||
* Generate an endpoint for an intersection, given four points.
|
||||
*/
|
||||
public SegmentEndpoint(final GeoPoint point,
|
||||
final SidedPlane prevCutoffPlane, final SidedPlane nextCutoffPlane,
|
||||
final GeoPoint prevUpperGeoPoint, final GeoPoint prevLowerGeoPoint,
|
||||
final GeoPoint nextUpperGeoPoint, final GeoPoint nextLowerGeoPoint) {
|
||||
// Note: What we really need is a single plane that goes through all four points.
|
||||
// Since that's not possible in the ellipsoid case (because three points determine a plane, not four), we
|
||||
// need an approximation that at least creates a boundary that has no interruptions.
|
||||
// There are three obvious choices for the third point: either (a) one of the two remaining points, or (b) the top or bottom edge
|
||||
// intersection point. (a) has no guarantee of continuity, while (b) is capable of producing something very far from a circle if
|
||||
// the angle between segments is acute.
|
||||
// The solution is to look for the side (top or bottom) that has an intersection within the shape. We use the two points from
|
||||
// the opposite side to determine the plane, AND we pick the third to be either of the two points on the intersecting side
|
||||
// PROVIDED that the other point is within the final circle we come up with.
|
||||
this.point = point;
|
||||
|
||||
// We construct four separate planes, and evaluate which one includes all interior points with least overlap
|
||||
final SidedPlane candidate1 = SidedPlane.constructNormalizedThreePointSidedPlane(point, prevUpperGeoPoint, nextUpperGeoPoint, nextLowerGeoPoint);
|
||||
final SidedPlane candidate2 = SidedPlane.constructNormalizedThreePointSidedPlane(point, nextUpperGeoPoint, nextLowerGeoPoint, prevLowerGeoPoint);
|
||||
final SidedPlane candidate3 = SidedPlane.constructNormalizedThreePointSidedPlane(point, nextLowerGeoPoint, prevLowerGeoPoint, prevUpperGeoPoint);
|
||||
final SidedPlane candidate4 = SidedPlane.constructNormalizedThreePointSidedPlane(point, prevLowerGeoPoint, prevUpperGeoPoint, nextUpperGeoPoint);
|
||||
|
||||
public void setCutoffPlanes(final GeoPoint[] previousEndNotablePoints, final Membership previousEndPlane,
|
||||
final GeoPoint[] nextStartNotablePoints, final Membership nextStartPlane) {
|
||||
if (previousEndNotablePoints == null && nextStartNotablePoints == null) {
|
||||
cutoffPlanes = new Membership[0];
|
||||
notablePoints = new GeoPoint[0];
|
||||
} else if (previousEndNotablePoints != null && nextStartNotablePoints == null) {
|
||||
cutoffPlanes = new Membership[]{previousEndPlane};
|
||||
notablePoints = previousEndNotablePoints;
|
||||
} else if (previousEndNotablePoints == null && nextStartNotablePoints != null) {
|
||||
cutoffPlanes = new Membership[]{nextStartPlane};
|
||||
notablePoints = nextStartNotablePoints;
|
||||
final boolean cand1IsOtherWithin = candidate1.isWithin(prevLowerGeoPoint);
|
||||
final boolean cand2IsOtherWithin = candidate2.isWithin(prevUpperGeoPoint);
|
||||
final boolean cand3IsOtherWithin = candidate3.isWithin(nextUpperGeoPoint);
|
||||
final boolean cand4IsOtherWithin = candidate4.isWithin(nextLowerGeoPoint);
|
||||
|
||||
if (cand1IsOtherWithin && cand2IsOtherWithin && cand3IsOtherWithin && cand4IsOtherWithin) {
|
||||
// The only way we should see both within is if all four points are coplanar. In that case, we default to the simplest treatment.
|
||||
this.circlePlane = candidate1; // doesn't matter which
|
||||
this.notablePoints = new GeoPoint[]{prevUpperGeoPoint, nextUpperGeoPoint, prevLowerGeoPoint, nextLowerGeoPoint};
|
||||
this.cutoffPlanes = new Membership[]{new SidedPlane(prevCutoffPlane), new SidedPlane(nextCutoffPlane)};
|
||||
} else if (cand1IsOtherWithin) {
|
||||
// Use candidate1, and DON'T include prevCutoffPlane in the cutoff planes list
|
||||
this.circlePlane = candidate1;
|
||||
this.notablePoints = new GeoPoint[]{prevUpperGeoPoint, nextUpperGeoPoint, nextLowerGeoPoint};
|
||||
this.cutoffPlanes = new Membership[]{new SidedPlane(nextCutoffPlane)};
|
||||
} else if (cand2IsOtherWithin) {
|
||||
// Use candidate2
|
||||
this.circlePlane = candidate2;
|
||||
this.notablePoints = new GeoPoint[]{nextUpperGeoPoint, nextLowerGeoPoint, prevLowerGeoPoint};
|
||||
this.cutoffPlanes = new Membership[]{new SidedPlane(nextCutoffPlane)};
|
||||
} else if (cand3IsOtherWithin) {
|
||||
this.circlePlane = candidate3;
|
||||
this.notablePoints = new GeoPoint[]{nextLowerGeoPoint, prevLowerGeoPoint, prevUpperGeoPoint};
|
||||
this.cutoffPlanes = new Membership[]{new SidedPlane(prevCutoffPlane)};
|
||||
} else if (cand4IsOtherWithin) {
|
||||
this.circlePlane = candidate4;
|
||||
this.notablePoints = new GeoPoint[]{prevLowerGeoPoint, prevUpperGeoPoint, nextUpperGeoPoint};
|
||||
this.cutoffPlanes = new Membership[]{new SidedPlane(prevCutoffPlane)};
|
||||
} else {
|
||||
cutoffPlanes = new Membership[]{previousEndPlane, nextStartPlane};
|
||||
notablePoints = new GeoPoint[previousEndNotablePoints.length + nextStartNotablePoints.length];
|
||||
int i = 0;
|
||||
for (GeoPoint p : previousEndNotablePoints) {
|
||||
notablePoints[i++] = p;
|
||||
}
|
||||
for (GeoPoint p : nextStartNotablePoints) {
|
||||
notablePoints[i++] = p;
|
||||
}
|
||||
// dunno what happened
|
||||
throw new RuntimeException("Couldn't come up with a plane through three points that included the fourth");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isWithin(final Vector point) {
|
||||
if (circlePlane == null)
|
||||
return false;
|
||||
return circlePlane.isWithin(point);
|
||||
}
|
||||
|
||||
public boolean isWithin(final double x, final double y, final double z) {
|
||||
if (circlePlane == null)
|
||||
return false;
|
||||
return circlePlane.isWithin(x, y, z);
|
||||
}
|
||||
|
||||
public double pathDistance(final GeoPoint point) {
|
||||
double dist = this.point.arcDistance(point);
|
||||
if (dist > cutoffAngle)
|
||||
if (!isWithin(point))
|
||||
return Double.MAX_VALUE;
|
||||
return dist;
|
||||
return this.point.arcDistance(point);
|
||||
}
|
||||
|
||||
public double pathNormalDistance(final GeoPoint point) {
|
||||
double dist = this.point.normalDistance(point);
|
||||
if (dist > cutoffNormalDistance)
|
||||
if (!isWithin(point))
|
||||
return Double.MAX_VALUE;
|
||||
return dist;
|
||||
return this.point.normalDistance(point);
|
||||
}
|
||||
|
||||
public double pathLinearDistance(final GeoPoint point) {
|
||||
double dist = this.point.linearDistance(point);
|
||||
if (dist > chordDistance)
|
||||
if (!isWithin(point))
|
||||
return Double.MAX_VALUE;
|
||||
return dist;
|
||||
return this.point.linearDistance(point);
|
||||
}
|
||||
|
||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
|
||||
return circlePlane.intersects(p, notablePoints, this.notablePoints, bounds, this.cutoffPlanes);
|
||||
public boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
|
||||
//System.err.println(" looking for intersection between plane "+p+" and circle "+circlePlane+" on proper side of "+cutoffPlanes+" within "+bounds);
|
||||
if (circlePlane == null)
|
||||
return false;
|
||||
return circlePlane.intersects(planetModel, p, notablePoints, this.notablePoints, bounds, this.cutoffPlanes);
|
||||
}
|
||||
|
||||
public void getBounds(Bounds bounds) {
|
||||
public void getBounds(final PlanetModel planetModel, Bounds bounds) {
|
||||
bounds.addPoint(point);
|
||||
circlePlane.recordBounds(bounds);
|
||||
if (circlePlane == null)
|
||||
return;
|
||||
circlePlane.recordBounds(planetModel, bounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -494,69 +588,70 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
|||
public final SidedPlane lowerConnectingPlane;
|
||||
public final SidedPlane startCutoffPlane;
|
||||
public final SidedPlane endCutoffPlane;
|
||||
public final GeoPoint URHC;
|
||||
public final GeoPoint LRHC;
|
||||
public final GeoPoint ULHC;
|
||||
public final GeoPoint LLHC;
|
||||
public final GeoPoint[] upperConnectingPlanePoints;
|
||||
public final GeoPoint[] lowerConnectingPlanePoints;
|
||||
public final GeoPoint[] startCutoffPlanePoints;
|
||||
public final GeoPoint[] endCutoffPlanePoints;
|
||||
public final double planeBoundingOffset;
|
||||
public final double arcWidth;
|
||||
public final double chordDistance;
|
||||
|
||||
// For the adjoining SegmentEndpoint...
|
||||
public final SidedPlane invertedStartCutoffPlane;
|
||||
public final SidedPlane invertedEndCutoffPlane;
|
||||
|
||||
public PathSegment(final GeoPoint start, final GeoPoint end, final double planeBoundingOffset, final double arcWidth, final double chordDistance) {
|
||||
public PathSegment(final PlanetModel planetModel, final GeoPoint start, final GeoPoint end,
|
||||
final Plane normalizedConnectingPlane, final double planeBoundingOffset) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.normalizedConnectingPlane = normalizedConnectingPlane;
|
||||
this.planeBoundingOffset = planeBoundingOffset;
|
||||
this.arcWidth = arcWidth;
|
||||
this.chordDistance = chordDistance;
|
||||
|
||||
fullDistance = start.arcDistance(end);
|
||||
fullNormalDistance = start.normalDistance(end);
|
||||
fullLinearDistance = start.linearDistance(end);
|
||||
normalizedConnectingPlane = new Plane(start, end).normalize();
|
||||
if (normalizedConnectingPlane == null) {
|
||||
upperConnectingPlane = null;
|
||||
lowerConnectingPlane = null;
|
||||
startCutoffPlane = null;
|
||||
endCutoffPlane = null;
|
||||
upperConnectingPlanePoints = null;
|
||||
lowerConnectingPlanePoints = null;
|
||||
startCutoffPlanePoints = null;
|
||||
endCutoffPlanePoints = null;
|
||||
invertedStartCutoffPlane = null;
|
||||
invertedEndCutoffPlane = null;
|
||||
} else {
|
||||
// Either start or end should be on the correct side
|
||||
upperConnectingPlane = new SidedPlane(start, normalizedConnectingPlane, -planeBoundingOffset);
|
||||
lowerConnectingPlane = new SidedPlane(start, normalizedConnectingPlane, planeBoundingOffset);
|
||||
// Cutoff planes use opposite endpoints as correct side examples
|
||||
startCutoffPlane = new SidedPlane(end, normalizedConnectingPlane, start);
|
||||
endCutoffPlane = new SidedPlane(start, normalizedConnectingPlane, end);
|
||||
final Membership[] upperSide = new Membership[]{upperConnectingPlane};
|
||||
final Membership[] lowerSide = new Membership[]{lowerConnectingPlane};
|
||||
final Membership[] startSide = new Membership[]{startCutoffPlane};
|
||||
final Membership[] endSide = new Membership[]{endCutoffPlane};
|
||||
final GeoPoint ULHC = upperConnectingPlane.findIntersections(startCutoffPlane, lowerSide, endSide)[0];
|
||||
final GeoPoint URHC = upperConnectingPlane.findIntersections(endCutoffPlane, lowerSide, startSide)[0];
|
||||
final GeoPoint LLHC = lowerConnectingPlane.findIntersections(startCutoffPlane, upperSide, endSide)[0];
|
||||
final GeoPoint LRHC = lowerConnectingPlane.findIntersections(endCutoffPlane, upperSide, startSide)[0];
|
||||
upperConnectingPlanePoints = new GeoPoint[]{ULHC, URHC};
|
||||
lowerConnectingPlanePoints = new GeoPoint[]{LLHC, LRHC};
|
||||
startCutoffPlanePoints = new GeoPoint[]{ULHC, LLHC};
|
||||
endCutoffPlanePoints = new GeoPoint[]{URHC, LRHC};
|
||||
invertedStartCutoffPlane = new SidedPlane(startCutoffPlane);
|
||||
invertedEndCutoffPlane = new SidedPlane(endCutoffPlane);
|
||||
// Either start or end should be on the correct side
|
||||
upperConnectingPlane = new SidedPlane(start, normalizedConnectingPlane, -planeBoundingOffset);
|
||||
lowerConnectingPlane = new SidedPlane(start, normalizedConnectingPlane, planeBoundingOffset);
|
||||
// Cutoff planes use opposite endpoints as correct side examples
|
||||
startCutoffPlane = new SidedPlane(end, normalizedConnectingPlane, start);
|
||||
endCutoffPlane = new SidedPlane(start, normalizedConnectingPlane, end);
|
||||
final Membership[] upperSide = new Membership[]{upperConnectingPlane};
|
||||
final Membership[] lowerSide = new Membership[]{lowerConnectingPlane};
|
||||
final Membership[] startSide = new Membership[]{startCutoffPlane};
|
||||
final Membership[] endSide = new Membership[]{endCutoffPlane};
|
||||
GeoPoint[] points;
|
||||
points = upperConnectingPlane.findIntersections(planetModel, startCutoffPlane, lowerSide, endSide);
|
||||
if (points.length == 0) {
|
||||
throw new IllegalArgumentException("Some segment boundary points are off the ellipsoid; path too wide");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDegenerate() {
|
||||
return normalizedConnectingPlane == null;
|
||||
this.ULHC = points[0];
|
||||
points = upperConnectingPlane.findIntersections(planetModel, endCutoffPlane, lowerSide, startSide);
|
||||
if (points.length == 0) {
|
||||
throw new IllegalArgumentException("Some segment boundary points are off the ellipsoid; path too wide");
|
||||
}
|
||||
this.URHC = points[0];
|
||||
points = lowerConnectingPlane.findIntersections(planetModel, startCutoffPlane, upperSide, endSide);
|
||||
if (points.length == 0) {
|
||||
throw new IllegalArgumentException("Some segment boundary points are off the ellipsoid; path too wide");
|
||||
}
|
||||
this.LLHC = points[0];
|
||||
points = lowerConnectingPlane.findIntersections(planetModel, endCutoffPlane, upperSide, startSide);
|
||||
if (points.length == 0) {
|
||||
throw new IllegalArgumentException("Some segment boundary points are off the ellipsoid; path too wide");
|
||||
}
|
||||
this.LRHC = points[0];
|
||||
upperConnectingPlanePoints = new GeoPoint[]{ULHC, URHC};
|
||||
lowerConnectingPlanePoints = new GeoPoint[]{LLHC, LRHC};
|
||||
startCutoffPlanePoints = new GeoPoint[]{ULHC, LLHC};
|
||||
endCutoffPlanePoints = new GeoPoint[]{URHC, LRHC};
|
||||
}
|
||||
|
||||
public boolean isWithin(final Vector point) {
|
||||
//System.err.println(" assessing whether point "+point+" is within path segment "+this);
|
||||
//System.err.println(" within "+startCutoffPlane+": "+startCutoffPlane.isWithin(point));
|
||||
//System.err.println(" within "+endCutoffPlane+": "+endCutoffPlane.isWithin(point));
|
||||
//System.err.println(" within "+upperConnectingPlane+": "+upperConnectingPlane.isWithin(point));
|
||||
//System.err.println(" within "+lowerConnectingPlane+": "+lowerConnectingPlane.isWithin(point));
|
||||
|
||||
return startCutoffPlane.isWithin(point) &&
|
||||
endCutoffPlane.isWithin(point) &&
|
||||
upperConnectingPlane.isWithin(point) &&
|
||||
|
@ -640,22 +735,22 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
|||
return point.linearDistance(normLineX, normLineY, normLineZ) + start.linearDistance(normLineX, normLineY, normLineZ);
|
||||
}
|
||||
|
||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
|
||||
return upperConnectingPlane.intersects(p, notablePoints, upperConnectingPlanePoints, bounds, lowerConnectingPlane, startCutoffPlane, endCutoffPlane) ||
|
||||
lowerConnectingPlane.intersects(p, notablePoints, lowerConnectingPlanePoints, bounds, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
|
||||
public boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
|
||||
return upperConnectingPlane.intersects(planetModel, p, notablePoints, upperConnectingPlanePoints, bounds, lowerConnectingPlane, startCutoffPlane, endCutoffPlane) ||
|
||||
lowerConnectingPlane.intersects(planetModel, p, notablePoints, lowerConnectingPlanePoints, bounds, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
|
||||
}
|
||||
|
||||
public void getBounds(Bounds bounds) {
|
||||
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(startCutoffPlane, bounds, lowerConnectingPlane, endCutoffPlane);
|
||||
startCutoffPlane.recordBounds(lowerConnectingPlane, bounds, endCutoffPlane, upperConnectingPlane);
|
||||
lowerConnectingPlane.recordBounds(endCutoffPlane, bounds, upperConnectingPlane, startCutoffPlane);
|
||||
endCutoffPlane.recordBounds(upperConnectingPlane, bounds, startCutoffPlane, lowerConnectingPlane);
|
||||
upperConnectingPlane.recordBounds(bounds, lowerConnectingPlane, startCutoffPlane, endCutoffPlane);
|
||||
lowerConnectingPlane.recordBounds(bounds, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
|
||||
startCutoffPlane.recordBounds(bounds, endCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
|
||||
endCutoffPlane.recordBounds(bounds, startCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
|
||||
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);
|
||||
if (fullDistance >= Math.PI) {
|
||||
// Too large a segment basically means that we can confuse the Bounds object. Specifically, if our span exceeds 180 degrees
|
||||
// in longitude (which even a segment whose actual length is less than that might if it goes close to a pole).
|
||||
|
|
|
@ -23,20 +23,36 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
* @lucene.experimental
|
||||
*/
|
||||
public class GeoPoint extends Vector {
|
||||
public GeoPoint(final double sinLat, final double sinLon, final double cosLat, final double cosLon) {
|
||||
super(cosLat * cosLon, cosLat * sinLon, sinLat);
|
||||
|
||||
protected double magnitude = Double.NEGATIVE_INFINITY;
|
||||
|
||||
public GeoPoint(final PlanetModel planetModel, final double sinLat, final double sinLon, final double cosLat, final double cosLon) {
|
||||
this(computeMagnitude(planetModel, cosLat * cosLon, cosLat * sinLon, sinLat),
|
||||
cosLat * cosLon, cosLat * sinLon, sinLat);
|
||||
}
|
||||
|
||||
public GeoPoint(final double lat, final double lon) {
|
||||
this(Math.sin(lat), Math.sin(lon), Math.cos(lat), Math.cos(lon));
|
||||
public GeoPoint(final PlanetModel planetModel, final double lat, final double lon) {
|
||||
this(planetModel, Math.sin(lat), Math.sin(lon), Math.cos(lat), Math.cos(lon));
|
||||
}
|
||||
|
||||
public GeoPoint(final double magnitude, final double x, final double y, final double z) {
|
||||
super(x * magnitude, y * magnitude, z * magnitude);
|
||||
this.magnitude = magnitude;
|
||||
}
|
||||
|
||||
public GeoPoint(final double x, final double y, final double z) {
|
||||
super(x, y, z);
|
||||
}
|
||||
|
||||
public double arcDistance(final GeoPoint v) {
|
||||
return Tools.safeAcos(dotProduct(v));
|
||||
return Tools.safeAcos(dotProduct(v)/(magnitude() * v.magnitude()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double magnitude() {
|
||||
if (this.magnitude == Double.NEGATIVE_INFINITY) {
|
||||
this.magnitude = super.magnitude();
|
||||
}
|
||||
return magnitude;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,16 +38,16 @@ public class GeoPolygonFactory {
|
|||
* its neighbors determines inside/outside for the entire polygon.
|
||||
* @return a GeoMembershipShape corresponding to what was specified.
|
||||
*/
|
||||
public static GeoMembershipShape makeGeoPolygon(List<GeoPoint> pointList, int convexPointIndex) {
|
||||
public static GeoMembershipShape makeGeoPolygon(final PlanetModel planetModel, final List<GeoPoint> pointList, final int convexPointIndex) {
|
||||
// The basic operation uses a set of points, two points determining one particular edge, and a sided plane
|
||||
// describing membership.
|
||||
return buildPolygonShape(pointList, convexPointIndex, getLegalIndex(convexPointIndex + 1, pointList.size()),
|
||||
return buildPolygonShape(planetModel, pointList, convexPointIndex, getLegalIndex(convexPointIndex + 1, pointList.size()),
|
||||
new SidedPlane(pointList.get(getLegalIndex(convexPointIndex - 1, pointList.size())),
|
||||
pointList.get(convexPointIndex), pointList.get(getLegalIndex(convexPointIndex + 1, pointList.size()))),
|
||||
false);
|
||||
}
|
||||
|
||||
public static GeoMembershipShape buildPolygonShape(List<GeoPoint> pointsList, int startPointIndex, int endPointIndex, SidedPlane startingEdge, boolean isInternalEdge) {
|
||||
public static GeoMembershipShape buildPolygonShape(final PlanetModel planetModel, final List<GeoPoint> pointsList, final int startPointIndex, final int endPointIndex, final SidedPlane startingEdge, final boolean isInternalEdge) {
|
||||
// Algorithm as follows:
|
||||
// Start with sided edge. Go through all points in some order. For each new point, determine if the point is within all edges considered so far.
|
||||
// If not, put it into a list of points for recursion. If it is within, add new edge and keep going.
|
||||
|
@ -112,7 +112,7 @@ public class GeoPolygonFactory {
|
|||
}
|
||||
// We want the other side for the recursion
|
||||
SidedPlane otherSideNewBoundary = new SidedPlane(newBoundary);
|
||||
rval.addShape(buildPolygonShape(recursionList, recursionList.size() - 2, recursionList.size() - 1, otherSideNewBoundary, true));
|
||||
rval.addShape(buildPolygonShape(planetModel, recursionList, recursionList.size() - 2, recursionList.size() - 1, otherSideNewBoundary, true));
|
||||
recursionList.clear();
|
||||
}
|
||||
currentList.add(newPoint);
|
||||
|
@ -140,11 +140,11 @@ public class GeoPolygonFactory {
|
|||
SidedPlane newBoundary = new SidedPlane(currentList.get(currentList.size() - 2), currentList.get(0), currentList.get(currentList.size() - 1));
|
||||
// We want the other side for the recursion
|
||||
SidedPlane otherSideNewBoundary = new SidedPlane(newBoundary);
|
||||
rval.addShape(buildPolygonShape(recursionList, recursionList.size() - 2, recursionList.size() - 1, otherSideNewBoundary, true));
|
||||
rval.addShape(buildPolygonShape(planetModel, recursionList, recursionList.size() - 2, recursionList.size() - 1, otherSideNewBoundary, true));
|
||||
recursionList.clear();
|
||||
}
|
||||
// Now, add in the current shape.
|
||||
rval.addShape(new GeoConvexPolygon(currentList, internalEdgeList, returnEdgeInternalBoundary));
|
||||
rval.addShape(new GeoConvexPolygon(planetModel, currentList, internalEdgeList, returnEdgeInternalBoundary));
|
||||
//System.out.println("Done creating polygon");
|
||||
return rval;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoRectangle extends GeoBBoxBase {
|
||||
public class GeoRectangle extends GeoBaseBBox {
|
||||
public final double topLat;
|
||||
public final double bottomLat;
|
||||
public final double leftLon;
|
||||
|
@ -54,7 +54,8 @@ public class GeoRectangle extends GeoBBoxBase {
|
|||
/**
|
||||
* Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
|
||||
*/
|
||||
public GeoRectangle(final double topLat, final double bottomLat, final double leftLon, double rightLon) {
|
||||
public GeoRectangle(final PlanetModel planetModel, final double topLat, final double bottomLat, final double leftLon, double rightLon) {
|
||||
super(planetModel);
|
||||
// Argument checking
|
||||
if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
|
||||
throw new IllegalArgumentException("Top latitude out of range");
|
||||
|
@ -88,10 +89,10 @@ public class GeoRectangle extends GeoBBoxBase {
|
|||
final double cosRightLon = Math.cos(rightLon);
|
||||
|
||||
// Now build the four points
|
||||
this.ULHC = new GeoPoint(sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
|
||||
this.URHC = new GeoPoint(sinTopLat, sinRightLon, cosTopLat, cosRightLon);
|
||||
this.LRHC = new GeoPoint(sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
|
||||
this.LLHC = new GeoPoint(sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
|
||||
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);
|
||||
|
||||
final double middleLat = (topLat + bottomLat) * 0.5;
|
||||
final double sinMiddleLat = Math.sin(middleLat);
|
||||
|
@ -104,10 +105,10 @@ public class GeoRectangle extends GeoBBoxBase {
|
|||
final double sinMiddleLon = Math.sin(middleLon);
|
||||
final double cosMiddleLon = Math.cos(middleLon);
|
||||
|
||||
this.centerPoint = new GeoPoint(sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
|
||||
this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
|
||||
|
||||
this.topPlane = new SidedPlane(centerPoint, sinTopLat);
|
||||
this.bottomPlane = new SidedPlane(centerPoint, sinBottomLat);
|
||||
this.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
|
||||
this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
|
||||
this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||
|
||||
|
@ -133,7 +134,7 @@ public class GeoRectangle extends GeoBBoxBase {
|
|||
newLeftLon = -Math.PI;
|
||||
newRightLon = Math.PI;
|
||||
}
|
||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -180,10 +181,10 @@ public class GeoRectangle extends GeoBBoxBase {
|
|||
|
||||
@Override
|
||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
return p.intersects(topPlane, notablePoints, topPlanePoints, bounds, bottomPlane, leftPlane, rightPlane) ||
|
||||
p.intersects(bottomPlane, notablePoints, bottomPlanePoints, bounds, topPlane, leftPlane, rightPlane) ||
|
||||
p.intersects(leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, topPlane, bottomPlane) ||
|
||||
p.intersects(rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, topPlane, bottomPlane);
|
||||
return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, bottomPlane, leftPlane, rightPlane) ||
|
||||
p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, topPlane, leftPlane, rightPlane) ||
|
||||
p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, topPlane, bottomPlane) ||
|
||||
p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, topPlane, bottomPlane);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -246,19 +247,20 @@ public class GeoRectangle extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoRectangle))
|
||||
return false;
|
||||
GeoRectangle other = (GeoRectangle) o;
|
||||
return other.ULHC.equals(ULHC) && other.LRHC.equals(LRHC);
|
||||
return super.equals(other) && other.ULHC.equals(ULHC) && other.LRHC.equals(LRHC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = ULHC.hashCode();
|
||||
result = 31 * result + LRHC.hashCode();
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + ULHC.hashCode();
|
||||
result = 31 * result + LRHC.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoRectangle: {toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
return "GeoRectangle: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoSouthLatitudeZone extends GeoBBoxBase {
|
||||
public class GeoSouthLatitudeZone extends GeoBaseBBox {
|
||||
public final double topLat;
|
||||
public final double cosTopLat;
|
||||
public final SidedPlane topPlane;
|
||||
|
@ -34,22 +34,20 @@ public class GeoSouthLatitudeZone extends GeoBBoxBase {
|
|||
// Edge points
|
||||
public final GeoPoint[] edgePoints;
|
||||
|
||||
public GeoSouthLatitudeZone(final double topLat) {
|
||||
public GeoSouthLatitudeZone(final PlanetModel planetModel, final double topLat) {
|
||||
super(planetModel);
|
||||
this.topLat = topLat;
|
||||
|
||||
final double sinTopLat = Math.sin(topLat);
|
||||
this.cosTopLat = Math.cos(topLat);
|
||||
|
||||
// Construct sample points, so we get our sidedness right
|
||||
final Vector topPoint = new Vector(0.0, 0.0, sinTopLat);
|
||||
|
||||
// Compute an interior point. Pick one whose lat is between top and bottom.
|
||||
final double middleLat = (topLat - Math.PI * 0.5) * 0.5;
|
||||
final double sinMiddleLat = Math.sin(middleLat);
|
||||
this.interiorPoint = new GeoPoint(Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 0.0, sinMiddleLat);
|
||||
this.topBoundaryPoint = new GeoPoint(Math.sqrt(1.0 - sinTopLat * sinTopLat), 0.0, sinTopLat);
|
||||
this.interiorPoint = new GeoPoint(planetModel, sinMiddleLat, 0.0, Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 1.0);
|
||||
this.topBoundaryPoint = new GeoPoint(planetModel, sinTopLat, 0.0, Math.sqrt(1.0 - sinTopLat * sinTopLat), 1.0);
|
||||
|
||||
this.topPlane = new SidedPlane(interiorPoint, sinTopLat);
|
||||
this.topPlane = new SidedPlane(interiorPoint, planetModel, sinTopLat);
|
||||
|
||||
this.edgePoints = new GeoPoint[]{topBoundaryPoint};
|
||||
}
|
||||
|
@ -58,7 +56,7 @@ public class GeoSouthLatitudeZone extends GeoBBoxBase {
|
|||
public GeoBBox expand(final double angle) {
|
||||
final double newTopLat = topLat + angle;
|
||||
final double newBottomLat = -Math.PI * 0.5;
|
||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, -Math.PI, Math.PI);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, -Math.PI, Math.PI);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -98,7 +96,7 @@ public class GeoSouthLatitudeZone extends GeoBBoxBase {
|
|||
|
||||
@Override
|
||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
return p.intersects(topPlane, notablePoints, planePoints, bounds);
|
||||
return p.intersects(planetModel, topPlane, notablePoints, planePoints, bounds);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,18 +153,19 @@ public class GeoSouthLatitudeZone extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoSouthLatitudeZone))
|
||||
return false;
|
||||
GeoSouthLatitudeZone other = (GeoSouthLatitudeZone) o;
|
||||
return other.topPlane.equals(topPlane);
|
||||
return super.equals(other) && other.topBoundaryPoint.equals(topBoundaryPoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = topPlane.hashCode();
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + topBoundaryPoint.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoSouthLatitudeZone: {toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + ")}";
|
||||
return "GeoSouthLatitudeZone: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoSouthRectangle extends GeoBBoxBase {
|
||||
public class GeoSouthRectangle extends GeoBaseBBox {
|
||||
public final double topLat;
|
||||
public final double leftLon;
|
||||
public final double rightLon;
|
||||
|
@ -45,12 +45,13 @@ public class GeoSouthRectangle extends GeoBBoxBase {
|
|||
|
||||
public final GeoPoint centerPoint;
|
||||
|
||||
public final GeoPoint[] edgePoints = new GeoPoint[]{SOUTH_POLE};
|
||||
public final GeoPoint[] edgePoints;
|
||||
|
||||
/**
|
||||
* Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}
|
||||
*/
|
||||
public GeoSouthRectangle(final double topLat, final double leftLon, double rightLon) {
|
||||
public GeoSouthRectangle(final PlanetModel planetModel, final double topLat, final double leftLon, double rightLon) {
|
||||
super(planetModel);
|
||||
// Argument checking
|
||||
if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
|
||||
throw new IllegalArgumentException("Top latitude out of range");
|
||||
|
@ -77,8 +78,8 @@ public class GeoSouthRectangle extends GeoBBoxBase {
|
|||
final double cosRightLon = Math.cos(rightLon);
|
||||
|
||||
// Now build the four points
|
||||
this.ULHC = new GeoPoint(sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
|
||||
this.URHC = new GeoPoint(sinTopLat, sinRightLon, cosTopLat, cosRightLon);
|
||||
this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
|
||||
this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon);
|
||||
|
||||
final double middleLat = (topLat - Math.PI * 0.5) * 0.5;
|
||||
final double sinMiddleLat = Math.sin(middleLat);
|
||||
|
@ -91,15 +92,18 @@ public class GeoSouthRectangle extends GeoBBoxBase {
|
|||
final double sinMiddleLon = Math.sin(middleLon);
|
||||
final double cosMiddleLon = Math.cos(middleLon);
|
||||
|
||||
this.centerPoint = new GeoPoint(sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
|
||||
this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
|
||||
|
||||
this.topPlane = new SidedPlane(centerPoint, sinTopLat);
|
||||
this.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
|
||||
this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||
|
||||
this.topPlanePoints = new GeoPoint[]{ULHC, URHC};
|
||||
this.leftPlanePoints = new GeoPoint[]{ULHC, SOUTH_POLE};
|
||||
this.rightPlanePoints = new GeoPoint[]{URHC, SOUTH_POLE};
|
||||
this.leftPlanePoints = new GeoPoint[]{ULHC, planetModel.SOUTH_POLE};
|
||||
this.rightPlanePoints = new GeoPoint[]{URHC, planetModel.SOUTH_POLE};
|
||||
|
||||
this.edgePoints = new GeoPoint[]{planetModel.SOUTH_POLE};
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -116,7 +120,7 @@ public class GeoSouthRectangle extends GeoBBoxBase {
|
|||
newLeftLon = -Math.PI;
|
||||
newRightLon = Math.PI;
|
||||
}
|
||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -160,9 +164,9 @@ public class GeoSouthRectangle extends GeoBBoxBase {
|
|||
|
||||
@Override
|
||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
return p.intersects(topPlane, notablePoints, topPlanePoints, bounds, leftPlane, rightPlane) ||
|
||||
p.intersects(leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, topPlane) ||
|
||||
p.intersects(rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, topPlane);
|
||||
return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, leftPlane, rightPlane) ||
|
||||
p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, topPlane) ||
|
||||
p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, topPlane);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -192,7 +196,7 @@ public class GeoSouthRectangle extends GeoBBoxBase {
|
|||
return OVERLAPS;
|
||||
}
|
||||
|
||||
final boolean insideShape = path.isWithin(SOUTH_POLE);
|
||||
final boolean insideShape = path.isWithin(planetModel.SOUTH_POLE);
|
||||
|
||||
if (insideRectangle == ALL_INSIDE && insideShape) {
|
||||
//System.err.println(" inside of each other");
|
||||
|
@ -224,19 +228,20 @@ public class GeoSouthRectangle extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoSouthRectangle))
|
||||
return false;
|
||||
GeoSouthRectangle other = (GeoSouthRectangle) o;
|
||||
return other.ULHC.equals(ULHC) && other.URHC.equals(URHC);
|
||||
return super.equals(other) && other.ULHC.equals(ULHC) && other.URHC.equals(URHC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = ULHC.hashCode();
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + ULHC.hashCode();
|
||||
result = 31 * result + URHC.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoSouthRectangle: {toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
return "GeoSouthRectangle: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoWideDegenerateHorizontalLine extends GeoBBoxBase {
|
||||
public class GeoWideDegenerateHorizontalLine extends GeoBaseBBox {
|
||||
public final double latitude;
|
||||
public final double leftLon;
|
||||
public final double rightLon;
|
||||
|
@ -46,7 +46,8 @@ public class GeoWideDegenerateHorizontalLine extends GeoBBoxBase {
|
|||
* Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}.
|
||||
* Horizontal angle must be greater than or equal to PI.
|
||||
*/
|
||||
public GeoWideDegenerateHorizontalLine(final double latitude, final double leftLon, double rightLon) {
|
||||
public GeoWideDegenerateHorizontalLine(final PlanetModel planetModel, final double latitude, final double leftLon, double rightLon) {
|
||||
super(planetModel);
|
||||
// Argument checking
|
||||
if (latitude > Math.PI * 0.5 || latitude < -Math.PI * 0.5)
|
||||
throw new IllegalArgumentException("Latitude out of range");
|
||||
|
@ -73,10 +74,10 @@ public class GeoWideDegenerateHorizontalLine extends GeoBBoxBase {
|
|||
final double cosRightLon = Math.cos(rightLon);
|
||||
|
||||
// Now build the two points
|
||||
this.LHC = new GeoPoint(sinLatitude, sinLeftLon, cosLatitude, cosLeftLon);
|
||||
this.RHC = new GeoPoint(sinLatitude, sinRightLon, cosLatitude, cosRightLon);
|
||||
this.LHC = new GeoPoint(planetModel, sinLatitude, sinLeftLon, cosLatitude, cosLeftLon);
|
||||
this.RHC = new GeoPoint(planetModel, sinLatitude, sinRightLon, cosLatitude, cosRightLon);
|
||||
|
||||
this.plane = new Plane(sinLatitude);
|
||||
this.plane = new Plane(planetModel, sinLatitude);
|
||||
|
||||
// Normalize
|
||||
while (leftLon > rightLon) {
|
||||
|
@ -86,7 +87,7 @@ public class GeoWideDegenerateHorizontalLine extends GeoBBoxBase {
|
|||
double sinMiddleLon = Math.sin(middleLon);
|
||||
double cosMiddleLon = Math.cos(middleLon);
|
||||
|
||||
this.centerPoint = new GeoPoint(sinLatitude, sinMiddleLon, cosLatitude, cosMiddleLon);
|
||||
this.centerPoint = new GeoPoint(planetModel, sinLatitude, sinMiddleLon, cosLatitude, cosMiddleLon);
|
||||
|
||||
this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||
|
@ -112,7 +113,7 @@ public class GeoWideDegenerateHorizontalLine extends GeoBBoxBase {
|
|||
newLeftLon = -Math.PI;
|
||||
newRightLon = Math.PI;
|
||||
}
|
||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -160,7 +161,7 @@ public class GeoWideDegenerateHorizontalLine extends GeoBBoxBase {
|
|||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
// Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
|
||||
// requires crossing into the right part of the other. So intersection can ignore the left/right bounds.
|
||||
return p.intersects(plane, notablePoints, planePoints, bounds, eitherBound);
|
||||
return p.intersects(planetModel, plane, notablePoints, planePoints, bounds, eitherBound);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -199,19 +200,20 @@ public class GeoWideDegenerateHorizontalLine extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoWideDegenerateHorizontalLine))
|
||||
return false;
|
||||
GeoWideDegenerateHorizontalLine other = (GeoWideDegenerateHorizontalLine) o;
|
||||
return other.LHC.equals(LHC) && other.RHC.equals(RHC);
|
||||
return super.equals(other) && other.LHC.equals(LHC) && other.RHC.equals(RHC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = LHC.hashCode();
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + LHC.hashCode();
|
||||
result = 31 * result + RHC.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoWideDegenerateHorizontalLine: {latitude=" + latitude + "(" + latitude * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightLon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
return "GeoWideDegenerateHorizontalLine: {planetmodel="+planetModel+", latitude=" + latitude + "(" + latitude * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightLon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
|
||||
protected class EitherBound implements Membership {
|
||||
|
|
|
@ -23,24 +23,25 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoWideLongitudeSlice extends GeoBBoxBase {
|
||||
public class GeoWideLongitudeSlice extends GeoBaseBBox {
|
||||
public final double leftLon;
|
||||
public final double rightLon;
|
||||
|
||||
public final SidedPlane leftPlane;
|
||||
public final SidedPlane rightPlane;
|
||||
|
||||
public final static GeoPoint[] planePoints = new GeoPoint[]{NORTH_POLE, SOUTH_POLE};
|
||||
public final GeoPoint[] planePoints;
|
||||
|
||||
public final GeoPoint centerPoint;
|
||||
|
||||
public final static GeoPoint[] edgePoints = new GeoPoint[]{NORTH_POLE};
|
||||
public final GeoPoint[] edgePoints;
|
||||
|
||||
/**
|
||||
* Accepts only values in the following ranges: lon: {@code -PI -> PI}.
|
||||
* Horizantal angle must be greater than or equal to PI.
|
||||
*/
|
||||
public GeoWideLongitudeSlice(final double leftLon, double rightLon) {
|
||||
public GeoWideLongitudeSlice(final PlanetModel planetModel, final double leftLon, double rightLon) {
|
||||
super(planetModel);
|
||||
// Argument checking
|
||||
if (leftLon < -Math.PI || leftLon > Math.PI)
|
||||
throw new IllegalArgumentException("Left longitude out of range");
|
||||
|
@ -66,10 +67,13 @@ public class GeoWideLongitudeSlice extends GeoBBoxBase {
|
|||
rightLon += Math.PI * 2.0;
|
||||
}
|
||||
final double middleLon = (leftLon + rightLon) * 0.5;
|
||||
this.centerPoint = new GeoPoint(0.0, middleLon);
|
||||
this.centerPoint = new GeoPoint(planetModel, 0.0, middleLon);
|
||||
|
||||
this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||
|
||||
this.planePoints = new GeoPoint[]{planetModel.NORTH_POLE, planetModel.SOUTH_POLE};
|
||||
this.edgePoints = new GeoPoint[]{planetModel.NORTH_POLE};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -84,7 +88,7 @@ public class GeoWideLongitudeSlice extends GeoBBoxBase {
|
|||
newLeftLon = -Math.PI;
|
||||
newRightLon = Math.PI;
|
||||
}
|
||||
return GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, newLeftLon, newRightLon);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, Math.PI * 0.5, -Math.PI * 0.5, newLeftLon, newRightLon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -127,8 +131,8 @@ public class GeoWideLongitudeSlice extends GeoBBoxBase {
|
|||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
// Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
|
||||
// requires crossing into the right part of the other. So intersection can ignore the left/right bounds.
|
||||
return p.intersects(leftPlane, notablePoints, planePoints, bounds) ||
|
||||
p.intersects(rightPlane, notablePoints, planePoints, bounds);
|
||||
return p.intersects(planetModel, leftPlane, notablePoints, planePoints, bounds) ||
|
||||
p.intersects(planetModel, rightPlane, notablePoints, planePoints, bounds);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,7 +159,7 @@ public class GeoWideLongitudeSlice extends GeoBBoxBase {
|
|||
if (insideRectangle == SOME_INSIDE)
|
||||
return OVERLAPS;
|
||||
|
||||
final boolean insideShape = path.isWithin(NORTH_POLE);
|
||||
final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
|
||||
|
||||
if (insideRectangle == ALL_INSIDE && insideShape)
|
||||
return OVERLAPS;
|
||||
|
@ -178,15 +182,14 @@ public class GeoWideLongitudeSlice extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoWideLongitudeSlice))
|
||||
return false;
|
||||
GeoWideLongitudeSlice other = (GeoWideLongitudeSlice) o;
|
||||
return other.leftLon == leftLon && other.rightLon == rightLon;
|
||||
return super.equals(other) && other.leftLon == leftLon && other.rightLon == rightLon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result;
|
||||
long temp;
|
||||
temp = Double.doubleToLongBits(leftLon);
|
||||
result = (int) (temp ^ (temp >>> 32));
|
||||
int result = super.hashCode();
|
||||
long temp = Double.doubleToLongBits(leftLon);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
temp = Double.doubleToLongBits(rightLon);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
return result;
|
||||
|
@ -194,7 +197,7 @@ public class GeoWideLongitudeSlice extends GeoBBoxBase {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoWideLongitudeSlice: {leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
return "GeoWideLongitudeSlice: {planetmodel="+planetModel+", leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoWideNorthRectangle extends GeoBBoxBase {
|
||||
public class GeoWideNorthRectangle extends GeoBaseBBox {
|
||||
public final double bottomLat;
|
||||
public final double leftLon;
|
||||
public final double rightLon;
|
||||
|
@ -45,13 +45,14 @@ public class GeoWideNorthRectangle extends GeoBBoxBase {
|
|||
|
||||
public final EitherBound eitherBound;
|
||||
|
||||
public final GeoPoint[] edgePoints = new GeoPoint[]{NORTH_POLE};
|
||||
public final GeoPoint[] edgePoints;
|
||||
|
||||
/**
|
||||
* Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}.
|
||||
* Horizontal angle must be greater than or equal to PI.
|
||||
*/
|
||||
public GeoWideNorthRectangle(final double bottomLat, final double leftLon, double rightLon) {
|
||||
public GeoWideNorthRectangle(final PlanetModel planetModel, final double bottomLat, final double leftLon, double rightLon) {
|
||||
super(planetModel);
|
||||
// Argument checking
|
||||
if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
|
||||
throw new IllegalArgumentException("Bottom latitude out of range");
|
||||
|
@ -78,8 +79,8 @@ public class GeoWideNorthRectangle extends GeoBBoxBase {
|
|||
final double cosRightLon = Math.cos(rightLon);
|
||||
|
||||
// Now build the four points
|
||||
this.LRHC = new GeoPoint(sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
|
||||
this.LLHC = new GeoPoint(sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
|
||||
this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
|
||||
this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
|
||||
|
||||
final double middleLat = (Math.PI * 0.5 + bottomLat) * 0.5;
|
||||
final double sinMiddleLat = Math.sin(middleLat);
|
||||
|
@ -92,17 +93,18 @@ public class GeoWideNorthRectangle extends GeoBBoxBase {
|
|||
final double sinMiddleLon = Math.sin(middleLon);
|
||||
final double cosMiddleLon = Math.cos(middleLon);
|
||||
|
||||
this.centerPoint = new GeoPoint(sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
|
||||
this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
|
||||
|
||||
this.bottomPlane = new SidedPlane(centerPoint, sinBottomLat);
|
||||
this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
|
||||
this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||
|
||||
this.bottomPlanePoints = new GeoPoint[]{LLHC, LRHC};
|
||||
this.leftPlanePoints = new GeoPoint[]{NORTH_POLE, LLHC};
|
||||
this.rightPlanePoints = new GeoPoint[]{NORTH_POLE, LRHC};
|
||||
this.leftPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LLHC};
|
||||
this.rightPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LRHC};
|
||||
|
||||
this.eitherBound = new EitherBound();
|
||||
this.edgePoints = new GeoPoint[]{planetModel.NORTH_POLE};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -119,7 +121,7 @@ public class GeoWideNorthRectangle extends GeoBBoxBase {
|
|||
newLeftLon = -Math.PI;
|
||||
newRightLon = Math.PI;
|
||||
}
|
||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -168,9 +170,9 @@ public class GeoWideNorthRectangle extends GeoBBoxBase {
|
|||
// Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
|
||||
// requires crossing into the right part of the other. So intersection can ignore the left/right bounds.
|
||||
return
|
||||
p.intersects(bottomPlane, notablePoints, bottomPlanePoints, bounds, eitherBound) ||
|
||||
p.intersects(leftPlane, notablePoints, leftPlanePoints, bounds, bottomPlane) ||
|
||||
p.intersects(rightPlane, notablePoints, rightPlanePoints, bounds, bottomPlane);
|
||||
p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, eitherBound) ||
|
||||
p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, bottomPlane) ||
|
||||
p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, bottomPlane);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -200,7 +202,7 @@ public class GeoWideNorthRectangle extends GeoBBoxBase {
|
|||
return OVERLAPS;
|
||||
}
|
||||
|
||||
final boolean insideShape = path.isWithin(NORTH_POLE);
|
||||
final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
|
||||
|
||||
if (insideRectangle == ALL_INSIDE && insideShape) {
|
||||
//System.err.println(" both inside each other");
|
||||
|
@ -234,19 +236,20 @@ public class GeoWideNorthRectangle extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoWideNorthRectangle))
|
||||
return false;
|
||||
GeoWideNorthRectangle other = (GeoWideNorthRectangle) o;
|
||||
return other.LLHC.equals(LLHC) && other.LRHC.equals(LRHC);
|
||||
return super.equals(other) && other.LLHC.equals(LLHC) && other.LRHC.equals(LRHC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = LLHC.hashCode();
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + LLHC.hashCode();
|
||||
result = 31 * result + LRHC.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoWideNorthRectangle: {bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
return "GeoWideNorthRectangle: {planetmodel="+planetModel+", bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
|
||||
protected class EitherBound implements Membership {
|
||||
|
|
|
@ -23,7 +23,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoWideRectangle extends GeoBBoxBase {
|
||||
public class GeoWideRectangle extends GeoBaseBBox {
|
||||
public final double topLat;
|
||||
public final double bottomLat;
|
||||
public final double leftLon;
|
||||
|
@ -56,7 +56,8 @@ public class GeoWideRectangle extends GeoBBoxBase {
|
|||
* Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}.
|
||||
* Horizontal angle must be greater than or equal to PI.
|
||||
*/
|
||||
public GeoWideRectangle(final double topLat, final double bottomLat, final double leftLon, double rightLon) {
|
||||
public GeoWideRectangle(final PlanetModel planetModel, final double topLat, final double bottomLat, final double leftLon, double rightLon) {
|
||||
super(planetModel);
|
||||
// Argument checking
|
||||
if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
|
||||
throw new IllegalArgumentException("Top latitude out of range");
|
||||
|
@ -90,10 +91,10 @@ public class GeoWideRectangle extends GeoBBoxBase {
|
|||
final double cosRightLon = Math.cos(rightLon);
|
||||
|
||||
// Now build the four points
|
||||
this.ULHC = new GeoPoint(sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
|
||||
this.URHC = new GeoPoint(sinTopLat, sinRightLon, cosTopLat, cosRightLon);
|
||||
this.LRHC = new GeoPoint(sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
|
||||
this.LLHC = new GeoPoint(sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
|
||||
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);
|
||||
|
||||
final double middleLat = (topLat + bottomLat) * 0.5;
|
||||
final double sinMiddleLat = Math.sin(middleLat);
|
||||
|
@ -106,10 +107,10 @@ public class GeoWideRectangle extends GeoBBoxBase {
|
|||
final double sinMiddleLon = Math.sin(middleLon);
|
||||
final double cosMiddleLon = Math.cos(middleLon);
|
||||
|
||||
this.centerPoint = new GeoPoint(sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
|
||||
this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
|
||||
|
||||
this.topPlane = new SidedPlane(centerPoint, sinTopLat);
|
||||
this.bottomPlane = new SidedPlane(centerPoint, sinBottomLat);
|
||||
this.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
|
||||
this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
|
||||
this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||
|
||||
|
@ -137,7 +138,7 @@ public class GeoWideRectangle extends GeoBBoxBase {
|
|||
newLeftLon = -Math.PI;
|
||||
newRightLon = Math.PI;
|
||||
}
|
||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -186,10 +187,10 @@ public class GeoWideRectangle extends GeoBBoxBase {
|
|||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
// Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
|
||||
// requires crossing into the right part of the other. So intersection can ignore the left/right bounds.
|
||||
return p.intersects(topPlane, notablePoints, topPlanePoints, bounds, bottomPlane, eitherBound) ||
|
||||
p.intersects(bottomPlane, notablePoints, bottomPlanePoints, bounds, topPlane, eitherBound) ||
|
||||
p.intersects(leftPlane, notablePoints, leftPlanePoints, bounds, topPlane, bottomPlane) ||
|
||||
p.intersects(rightPlane, notablePoints, rightPlanePoints, bounds, topPlane, bottomPlane);
|
||||
return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, bottomPlane, eitherBound) ||
|
||||
p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, topPlane, eitherBound) ||
|
||||
p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, topPlane, bottomPlane) ||
|
||||
p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, topPlane, bottomPlane);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -253,19 +254,20 @@ public class GeoWideRectangle extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoWideRectangle))
|
||||
return false;
|
||||
GeoWideRectangle other = (GeoWideRectangle) o;
|
||||
return other.ULHC.equals(ULHC) && other.LRHC.equals(LRHC);
|
||||
return super.equals(other) && other.ULHC.equals(ULHC) && other.LRHC.equals(LRHC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = ULHC.hashCode();
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + ULHC.hashCode();
|
||||
result = 31 * result + LRHC.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoWideRectangle: {toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
return "GeoWideRectangle: {planetmodel=" + planetModel + ", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
|
||||
protected class EitherBound implements Membership {
|
||||
|
|
|
@ -23,7 +23,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoWideSouthRectangle extends GeoBBoxBase {
|
||||
public class GeoWideSouthRectangle extends GeoBaseBBox {
|
||||
public final double topLat;
|
||||
public final double leftLon;
|
||||
public final double rightLon;
|
||||
|
@ -45,13 +45,14 @@ public class GeoWideSouthRectangle extends GeoBBoxBase {
|
|||
|
||||
public final EitherBound eitherBound;
|
||||
|
||||
public final GeoPoint[] edgePoints = new GeoPoint[]{SOUTH_POLE};
|
||||
public final GeoPoint[] edgePoints;
|
||||
|
||||
/**
|
||||
* Accepts only values in the following ranges: lat: {@code -PI/2 -> PI/2}, lon: {@code -PI -> PI}.
|
||||
* Horizontal angle must be greater than or equal to PI.
|
||||
*/
|
||||
public GeoWideSouthRectangle(final double topLat, final double leftLon, double rightLon) {
|
||||
public GeoWideSouthRectangle(final PlanetModel planetModel, final double topLat, final double leftLon, double rightLon) {
|
||||
super(planetModel);
|
||||
// Argument checking
|
||||
if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
|
||||
throw new IllegalArgumentException("Top latitude out of range");
|
||||
|
@ -78,8 +79,8 @@ public class GeoWideSouthRectangle extends GeoBBoxBase {
|
|||
final double cosRightLon = Math.cos(rightLon);
|
||||
|
||||
// Now build the four points
|
||||
this.ULHC = new GeoPoint(sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
|
||||
this.URHC = new GeoPoint(sinTopLat, sinRightLon, cosTopLat, cosRightLon);
|
||||
this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
|
||||
this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon);
|
||||
|
||||
final double middleLat = (topLat - Math.PI * 0.5) * 0.5;
|
||||
final double sinMiddleLat = Math.sin(middleLat);
|
||||
|
@ -92,17 +93,19 @@ public class GeoWideSouthRectangle extends GeoBBoxBase {
|
|||
final double sinMiddleLon = Math.sin(middleLon);
|
||||
final double cosMiddleLon = Math.cos(middleLon);
|
||||
|
||||
this.centerPoint = new GeoPoint(sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
|
||||
this.centerPoint = new GeoPoint(planetModel, sinMiddleLat, sinMiddleLon, cosMiddleLat, cosMiddleLon);
|
||||
|
||||
this.topPlane = new SidedPlane(centerPoint, sinTopLat);
|
||||
this.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
|
||||
this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||
|
||||
this.topPlanePoints = new GeoPoint[]{ULHC, URHC};
|
||||
this.leftPlanePoints = new GeoPoint[]{ULHC, SOUTH_POLE};
|
||||
this.rightPlanePoints = new GeoPoint[]{URHC, SOUTH_POLE};
|
||||
this.leftPlanePoints = new GeoPoint[]{ULHC, planetModel.SOUTH_POLE};
|
||||
this.rightPlanePoints = new GeoPoint[]{URHC, planetModel.SOUTH_POLE};
|
||||
|
||||
this.eitherBound = new EitherBound();
|
||||
|
||||
this.edgePoints = new GeoPoint[]{planetModel.SOUTH_POLE};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -119,7 +122,7 @@ public class GeoWideSouthRectangle extends GeoBBoxBase {
|
|||
newLeftLon = -Math.PI;
|
||||
newRightLon = Math.PI;
|
||||
}
|
||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -165,9 +168,9 @@ public class GeoWideSouthRectangle extends GeoBBoxBase {
|
|||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||
// Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
|
||||
// requires crossing into the right part of the other. So intersection can ignore the left/right bounds.
|
||||
return p.intersects(topPlane, notablePoints, topPlanePoints, bounds, eitherBound) ||
|
||||
p.intersects(leftPlane, notablePoints, leftPlanePoints, bounds, topPlane) ||
|
||||
p.intersects(rightPlane, notablePoints, rightPlanePoints, bounds, topPlane);
|
||||
return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, eitherBound) ||
|
||||
p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, topPlane) ||
|
||||
p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, topPlane);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -197,7 +200,7 @@ public class GeoWideSouthRectangle extends GeoBBoxBase {
|
|||
return OVERLAPS;
|
||||
}
|
||||
|
||||
final boolean insideShape = path.isWithin(SOUTH_POLE);
|
||||
final boolean insideShape = path.isWithin(planetModel.SOUTH_POLE);
|
||||
|
||||
if (insideRectangle == ALL_INSIDE && insideShape) {
|
||||
//System.err.println(" both inside each other");
|
||||
|
@ -230,19 +233,20 @@ public class GeoWideSouthRectangle extends GeoBBoxBase {
|
|||
if (!(o instanceof GeoWideSouthRectangle))
|
||||
return false;
|
||||
GeoWideSouthRectangle other = (GeoWideSouthRectangle) o;
|
||||
return other.ULHC.equals(ULHC) && other.URHC.equals(URHC);
|
||||
return super.equals(other) && other.ULHC.equals(ULHC) && other.URHC.equals(URHC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = ULHC.hashCode();
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + ULHC.hashCode();
|
||||
result = 31 * result + URHC.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoWideSouthRectangle: {toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
return "GeoWideSouthRectangle: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), leftlon=" + leftLon + "(" + leftLon * 180.0 / Math.PI + "), rightlon=" + rightLon + "(" + rightLon * 180.0 / Math.PI + ")}";
|
||||
}
|
||||
|
||||
protected class EitherBound implements Membership {
|
||||
|
|
|
@ -22,11 +22,13 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
|||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class GeoWorld extends GeoBBoxBase {
|
||||
protected final static GeoPoint originPoint = new GeoPoint(1.0, 0.0, 0.0);
|
||||
public class GeoWorld extends GeoBaseBBox {
|
||||
protected final static GeoPoint[] edgePoints = new GeoPoint[0];
|
||||
|
||||
public GeoWorld() {
|
||||
protected final GeoPoint originPoint;
|
||||
|
||||
public GeoWorld(final PlanetModel planetModel) {
|
||||
super(planetModel);
|
||||
originPoint = new GeoPoint(planetModel.ab, 1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -100,16 +102,16 @@ public class GeoWorld extends GeoBBoxBase {
|
|||
public boolean equals(Object o) {
|
||||
if (!(o instanceof GeoWorld))
|
||||
return false;
|
||||
return true;
|
||||
return super.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 0;
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GeoWorld";
|
||||
return "GeoWorld: {planetmodel="+planetModel+"}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,11 +51,12 @@ public class Plane extends Vector {
|
|||
/**
|
||||
* Construct a horizontal plane at a specified Z.
|
||||
*
|
||||
* @param height is the specified Z coordinate.
|
||||
* @param planetModel is the planet model.
|
||||
* @param sinLat is the sin(latitude).
|
||||
*/
|
||||
public Plane(final double height) {
|
||||
public Plane(final PlanetModel planetModel, final double sinLat) {
|
||||
super(0.0, 0.0, 1.0);
|
||||
D = -height;
|
||||
D = -sinLat * computeMagnitude(planetModel, sinLat);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,6 +82,15 @@ public class Plane extends Vector {
|
|||
this.D = D;
|
||||
}
|
||||
|
||||
/** Construct a normalized, vertical plane through an x-y point. If the x-y point is at (0,0), return null.
|
||||
*/
|
||||
public static Plane constructNormalizedVerticalPlane(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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the plane equation for a given point, as represented
|
||||
* by a vector.
|
||||
|
@ -289,15 +299,27 @@ public class Plane extends Vector {
|
|||
return new GeoPoint(result.x, result.y, result.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public version of findIntersections.
|
||||
*/
|
||||
public GeoPoint[] findIntersections(final PlanetModel planetModel, final Plane q, final Membership... bounds) {
|
||||
if (isNumericallyIdentical(q)) {
|
||||
return null;
|
||||
}
|
||||
return findIntersections(planetModel, q, bounds, NO_BOUNDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the intersection points between two planes, given a set of bounds.
|
||||
*
|
||||
* @param planetModel is the planet model to use in finding points.
|
||||
* @param q is the plane to intersect with.
|
||||
* @param bounds is the set of bounds.
|
||||
* @param moreBounds is another set of bounds.
|
||||
* @return the intersection point(s) on the unit sphere, if there are any.
|
||||
*/
|
||||
protected GeoPoint[] findIntersections(final Plane q, final Membership[] bounds, final Membership[] moreBounds) {
|
||||
protected GeoPoint[] findIntersections(final PlanetModel planetModel, final Plane q, final Membership[] bounds, final Membership[] moreBounds) {
|
||||
//System.err.println("Looking for intersection between plane "+this+" and plane "+q+" within bounds");
|
||||
final Vector lineVector = new Vector(this, q);
|
||||
if (Math.abs(lineVector.x) < MINIMUM_RESOLUTION && Math.abs(lineVector.y) < MINIMUM_RESOLUTION && Math.abs(lineVector.z) < MINIMUM_RESOLUTION) {
|
||||
// Degenerate case: parallel planes
|
||||
|
@ -363,16 +385,18 @@ public class Plane extends Vector {
|
|||
z0 = 0.0;
|
||||
}
|
||||
|
||||
// Once an intersecting line is determined, the next step is to intersect that line with the unit sphere, which
|
||||
// Once an intersecting line is determined, the next step is to intersect that line with the ellipsoid, which
|
||||
// will yield zero, one, or two points.
|
||||
// The equation of the sphere is: 1.0 = x^2 + y^2 + z^2. Plugging in the parameterized line values yields:
|
||||
// 1.0 = (At+A0)^2 + (Bt+B0)^2 + (Ct+C0)^2
|
||||
// A^2 t^2 + 2AA0t + A0^2 + B^2 t^2 + 2BB0t + B0^2 + C^2 t^2 + 2CC0t + C0^2 - 1,0 = 0.0
|
||||
// [A^2 + B^2 + C^2] t^2 + [2AA0 + 2BB0 + 2CC0] t + [A0^2 + B0^2 + C0^2 - 1,0] = 0.0
|
||||
// The ellipsoid equation: 1,0 = x^2/a^2 + y^2/b^2 + z^2/c^2
|
||||
// 1.0 = (At+A0)^2/a^2 + (Bt+B0)^2/b^2 + (Ct+C0)^2/c^2
|
||||
// A^2 t^2 / a^2 + 2AA0t / a^2 + A0^2 / a^2 + B^2 t^2 / b^2 + 2BB0t / b^2 + B0^2 / b^2 + C^2 t^2 / c^2 + 2CC0t / c^2 + C0^2 / c^2 - 1,0 = 0.0
|
||||
// [A^2 / a^2 + B^2 / b^2 + C^2 / c^2] t^2 + [2AA0 / a^2 + 2BB0 / b^2 + 2CC0 / c^2] t + [A0^2 / a^2 + B0^2 / b^2 + C0^2 / c^2 - 1,0] = 0.0
|
||||
// Use the quadratic formula to determine t values and candidate point(s)
|
||||
final double A = lineVector.x * lineVector.x + lineVector.y * lineVector.y + lineVector.z * lineVector.z;
|
||||
final double B = 2.0 * (lineVector.x * x0 + lineVector.y * y0 + lineVector.z * z0);
|
||||
final double C = x0 * x0 + y0 * y0 + z0 * z0 - 1.0;
|
||||
final double A = lineVector.x * lineVector.x * planetModel.inverseAbSquared +
|
||||
lineVector.y * lineVector.y * planetModel.inverseAbSquared +
|
||||
lineVector.z * lineVector.z * planetModel.inverseCSquared;
|
||||
final double B = 2.0 * (lineVector.x * x0 * planetModel.inverseAbSquared + lineVector.y * y0 * planetModel.inverseAbSquared + lineVector.z * z0 * planetModel.inverseCSquared);
|
||||
final double C = x0 * x0 * planetModel.inverseAbSquared + y0 * y0 * planetModel.inverseAbSquared + z0 * z0 * planetModel.inverseCSquared - 1.0;
|
||||
|
||||
final double BsquaredMinus = B * B - 4.0 * A * C;
|
||||
if (Math.abs(BsquaredMinus) < MINIMUM_RESOLUTION_SQUARED) {
|
||||
|
@ -381,6 +405,8 @@ public class Plane extends Vector {
|
|||
// One solution only
|
||||
final double t = -B * inverse2A;
|
||||
GeoPoint point = new GeoPoint(lineVector.x * t + x0, lineVector.y * t + y0, lineVector.z * t + z0);
|
||||
//System.err.println(" point: "+point);
|
||||
//verifyPoint(planetModel, point, q);
|
||||
if (point.isWithin(bounds, moreBounds))
|
||||
return new GeoPoint[]{point};
|
||||
return NO_POINTS;
|
||||
|
@ -393,6 +419,8 @@ public class Plane extends Vector {
|
|||
final double t2 = (-B - sqrtTerm) * inverse2A;
|
||||
GeoPoint point1 = new GeoPoint(lineVector.x * t1 + x0, lineVector.y * t1 + y0, lineVector.z * t1 + z0);
|
||||
GeoPoint point2 = new GeoPoint(lineVector.x * t2 + x0, lineVector.y * t2 + y0, lineVector.z * t2 + z0);
|
||||
//verifyPoint(planetModel, point1, q);
|
||||
//verifyPoint(planetModel, point2, q);
|
||||
//System.err.println(" "+point1+" and "+point2);
|
||||
if (point1.isWithin(bounds, moreBounds)) {
|
||||
if (point2.isWithin(bounds, moreBounds))
|
||||
|
@ -408,18 +436,30 @@ public class Plane extends Vector {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
protected void verifyPoint(final PlanetModel planetModel, final GeoPoint point, final Plane q) {
|
||||
if (!evaluateIsZero(point))
|
||||
throw new RuntimeException("Intersection point not on original plane; point="+point+", plane="+this);
|
||||
if (!q.evaluateIsZero(point))
|
||||
throw new RuntimeException("Intersection point not on intersected plane; point="+point+", plane="+q);
|
||||
if (Math.abs(point.x * point.x * planetModel.inverseASquared + point.y * point.y * planetModel.inverseBSquared + point.z * point.z * planetModel.inverseCSquared - 1.0) >= MINIMUM_RESOLUTION)
|
||||
throw new RuntimeException("Intersection point not on ellipsoid; point="+point);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Accumulate 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
|
||||
* 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 bounds are the surfaces delineating what's inside the shape.
|
||||
*/
|
||||
public void recordBounds(final Plane q, final Bounds boundsInfo, final Membership... bounds) {
|
||||
final GeoPoint[] intersectionPoints = findIntersections(q, bounds, NO_BOUNDS);
|
||||
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);
|
||||
}
|
||||
|
@ -430,10 +470,11 @@ public class Plane extends Vector {
|
|||
* 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 bounds are the surfaces delineating what's inside the shape.
|
||||
*/
|
||||
public void recordBounds(final Bounds boundsInfo, final Membership... bounds) {
|
||||
public void recordBounds(final PlanetModel planetModel, final Bounds boundsInfo, final Membership... bounds) {
|
||||
// For clarity, load local variables with good names
|
||||
final double A = this.x;
|
||||
final double B = this.y;
|
||||
|
@ -442,236 +483,27 @@ public class Plane extends Vector {
|
|||
// Now compute latitude min/max points
|
||||
if (!boundsInfo.checkNoTopLatitudeBound() || !boundsInfo.checkNoBottomLatitudeBound()) {
|
||||
//System.err.println("Looking at latitude for plane "+this);
|
||||
// With ellipsoids, we really have only one viable way to do this computation.
|
||||
// Specifically, we compute an appropriate vertical plane, based on the current plane's x-y orientation, and
|
||||
// then intersect it with this one and with the ellipsoid. This gives us zero, one, or two points to use
|
||||
// as bounds.
|
||||
// There is one special case: horizontal circles. These require TWO vertical planes: one for the x, and one for
|
||||
// the y, and we use all four resulting points in the bounds computation.
|
||||
if ((Math.abs(A) >= MINIMUM_RESOLUTION || Math.abs(B) >= MINIMUM_RESOLUTION)) {
|
||||
//System.out.println("A = "+A+" B = "+B+" C = "+C+" D = "+D);
|
||||
// sin (phi) = z
|
||||
// cos (theta - phi) = D
|
||||
// sin (theta) = C (the dot product of (0,0,1) and (A,B,C) )
|
||||
// Q: what is z?
|
||||
//
|
||||
// cos (theta-phi) = cos(theta)cos(phi) + sin(theta)sin(phi) = D
|
||||
|
||||
if (Math.abs(C) < MINIMUM_RESOLUTION) {
|
||||
// Special case: circle is vertical.
|
||||
//System.err.println(" Degenerate case; it's vertical circle");
|
||||
// cos(phi) = D, and we want sin(phi) = z
|
||||
// There are two solutions for phi given cos(phi) = D: a positive solution and a negative solution.
|
||||
// So, when we compute z = sqrt(1-D^2), it's really z = +/- sqrt(1-D^2) .
|
||||
|
||||
double z;
|
||||
double x;
|
||||
double y;
|
||||
|
||||
final double denom = 1.0 / (A * A + B * B);
|
||||
|
||||
z = Math.sqrt(1.0 - D * D);
|
||||
y = -B * D * denom;
|
||||
x = -A * D * denom;
|
||||
addPoint(boundsInfo, bounds, x, y, z);
|
||||
|
||||
z = -z;
|
||||
addPoint(boundsInfo, bounds, x, y, z);
|
||||
} else if (Math.abs(D) < MINIMUM_RESOLUTION) {
|
||||
//System.err.println(" Plane through origin case");
|
||||
// The general case is degenerate when the plane goes through the origin.
|
||||
// Luckily there's a pretty good way to figure out the max and min for that case though.
|
||||
// We find the two z values by computing the angle of the plane's inclination with the normal.
|
||||
// E.g., if this.z == 1, then our z value is 0, and if this.z == 0, our z value is 1.
|
||||
// Also if this.z == -1, then z value is 0 again.
|
||||
// Another way of putting this is that our z = sqrt(this.x^2 + this.y^2).
|
||||
//
|
||||
// The only tricky part is computing x and y.
|
||||
double z;
|
||||
double x;
|
||||
double y;
|
||||
|
||||
final double denom = 1.0 / (A * A + B * B);
|
||||
|
||||
z = Math.sqrt((A * A + B * B) / (A * A + B * B + C * C));
|
||||
y = -B * (C * z) * denom;
|
||||
x = -A * (C * z) * denom;
|
||||
addPoint(boundsInfo, bounds, x, y, z);
|
||||
|
||||
z = -z;
|
||||
y = -B * (C * z) * denom;
|
||||
x = -A * (C * z) * denom;
|
||||
addPoint(boundsInfo, bounds, x, y, z);
|
||||
|
||||
} else {
|
||||
//System.err.println(" General latitude case");
|
||||
// We might be able to identify a specific new latitude maximum or minimum.
|
||||
//
|
||||
// cos (theta-phi) = cos(theta)cos(phi) + sin(theta)sin(phi) = D
|
||||
//
|
||||
// This is tricky. If cos(phi) = something, and we want to figure out
|
||||
// what sin(phi) is, in order to capture all solutions we need to recognize
|
||||
// that sin(phi) = +/- sqrt(1 - cos(phi)^2). Basically, this means that
|
||||
// whatever solution we find we have to mirror it across the x-y plane,
|
||||
// and include both +z and -z solutions.
|
||||
//
|
||||
// cos (phi) = +/- sqrt(1-sin(phi)^2) = +/- sqrt(1-z^2)
|
||||
// cos (theta) = +/- sqrt(1-sin(theta)^2) = +/- sqrt(1-C^2)
|
||||
//
|
||||
// D = cos(theta)cos(phi) + sin(theta)sin(phi)
|
||||
// Substitute:
|
||||
// D = sqrt(1-C^2) * sqrt(1-z^2) -/+ C * z
|
||||
// Solve for z...
|
||||
// D +/- Cz = sqrt(1-C^2)*sqrt(1-z^2) = sqrt(1 - z^2 - C^2 + z^2*C^2)
|
||||
// Square both sides.
|
||||
// (D +/- Cz)^2 = 1 - z^2 - C^2 + z^2*C^2
|
||||
// D^2 +/- 2DCz + C^2*z^2 = 1 - z^2 - C^2 + z^2*C^2
|
||||
// D^2 +/- 2DCz = 1 - C^2 - z^2
|
||||
// 0 = z^2 +/- 2DCz + (C^2 +D^2-1) = 0
|
||||
//
|
||||
// z = (+/- 2DC +/- sqrt(4*D^2*C^2 - 4*(C^2+D^2-1))) / (2)
|
||||
// z = +/- DC +/- sqrt(D^2*C^2 + 1 - C^2 - D^2 )
|
||||
// = +/- DC +/- sqrt(D^2*C^2 + 1 - C^2 - D^2)
|
||||
//
|
||||
// NOTE WELL: The above is clearly degenerate when D = 0. So we'll have to
|
||||
// code a different solution for that case!
|
||||
|
||||
// To get x and y, we need to plug z into the equations, as follows:
|
||||
//
|
||||
// Ax + By = -Cz - D
|
||||
// x^2 + y^2 = 1 - z^2
|
||||
//
|
||||
// x = (-Cz -D -By) /A
|
||||
// y = (-Cz -D -Ax) /B
|
||||
//
|
||||
// [(-Cz -D -By) /A]^2 + y^2 = 1 - z^2
|
||||
// [-Cz -D -By]^2 + A^2*y^2 = A^2 - A^2*z^2
|
||||
// C^2*z^2 + D^2 + B^2*y^2 + 2CDz + 2CBzy + 2DBy + A^2*y^2 - A^2 + A^2*z^2 = 0
|
||||
// y^2 [A^2 + B^2] + y [2DB + 2CBz] + [C^2*z^2 + D^2 + 2CDz - A^2 + A^2*z^2] = 0
|
||||
//
|
||||
//
|
||||
// Use quadratic formula, where:
|
||||
// a = [A^2 + B^2]
|
||||
// b = [2BD + 2CBz]
|
||||
// c = [C^2*z^2 + D^2 + 2CDz - A^2 + A^2*z^2]
|
||||
//
|
||||
// y = (-[2BD + 2CBz] +/- sqrt([2BD + 2CBz]^2 - 4 * [A^2 + B^2] * [C^2*z^2 + D^2 + 2CDz - A^2 + A^2*z^2]) ) / (2 * [A^2 + B^2])
|
||||
// Take out a 2:
|
||||
// y = (-[DB +CBz] +/- sqrt([DB + CBz]^2 - [A^2 + B^2] * [C^2*z^2 + D^2 + 2CDz - A^2 + A^2*z^2]) ) / [A^2 + B^2]
|
||||
//
|
||||
// The sqrt term simplifies:
|
||||
//
|
||||
// B^2*D^2 + C^2*B^2*z^2 + 2C*D*B^2*z - [A^2 + B^2] * [C^2*z^2 + D^2 + 2CDz - A^2 + A^2*z^2] = ?
|
||||
// B^2*D^2 + C^2*B^2*z^2 + 2C*D*B^2*z - [A^2 * C^2 * z^2 + A^2 * D^2 + 2 * A^2 * CDz - A^4 + A^4*z^2
|
||||
// + B^2 * C^2 * z^2 + B^2 * D^2 + 2 * B^2 * CDz - A^2 * B^2 + B^2 * A^2 * z^2] =?
|
||||
// C^2*B^2*z^2 + 2C*D*B^2*z - [A^2 * C^2 * z^2 + A^2 * D^2 + 2 * A^2 * CDz - A^4 + A^4*z^2
|
||||
// + B^2 * C^2 * z^2 + 2 * B^2 * CDz - A^2 * B^2 + B^2 * A^2 * z^2] =?
|
||||
// 2C*D*B^2*z - [A^2 * C^2 * z^2 + A^2 * D^2 + 2 * A^2 * CDz - A^4 + A^4*z^2
|
||||
// + 2 * B^2 * CDz - A^2 * B^2 + B^2 * A^2 * z^2] =?
|
||||
// - [A^2 * C^2 * z^2 + A^2 * D^2 + 2 * A^2 * CDz - A^4 + A^4*z^2
|
||||
// - A^2 * B^2 + B^2 * A^2 * z^2] =?
|
||||
// - A^2 * [C^2 * z^2 + D^2 + 2 * CDz - A^2 + A^2*z^2
|
||||
// - B^2 + B^2 * z^2] =?
|
||||
// - A^2 * [z^2[A^2 + B^2 + C^2] - [A^2 + B^2 - D^2] + 2CDz] =?
|
||||
// - A^2 * [z^2 - [A^2 + B^2 - D^2] + 2CDz] =?
|
||||
//
|
||||
// y = (-[DB +CBz] +/- A*sqrt([A^2 + B^2 - D^2] - z^2 - 2CDz) ) / [A^2 + B^2]
|
||||
//
|
||||
// correspondingly:
|
||||
// x = (-[DA +CAz] +/- B*sqrt([A^2 + B^2 - D^2] - z^2 - 2CDz) ) / [A^2 + B^2]
|
||||
//
|
||||
// However, for the maximum or minimum we seek, the clause inside the sqrt should be zero. If
|
||||
// it is NOT zero, then we aren't looking at the right z value.
|
||||
|
||||
double z;
|
||||
double x;
|
||||
double y;
|
||||
|
||||
double sqrtValue = D * D * C * C + 1.0 - C * C - D * D;
|
||||
double denom = 1.0 / (A * A + B * B);
|
||||
if (Math.abs(sqrtValue) < MINIMUM_RESOLUTION_SQUARED) {
|
||||
//System.err.println(" One latitude solution");
|
||||
double insideValue;
|
||||
double sqrtTerm;
|
||||
|
||||
z = D * C;
|
||||
// Since we squared both sides of the equation, we may have introduced spurious solutions, so we have to check.
|
||||
// But the same check applies to BOTH solutions -- the +z one as well as the -z one.
|
||||
insideValue = A * A + B * B - D * D - z * z - 2.0 * C * D * z;
|
||||
if (Math.abs(insideValue) < MINIMUM_RESOLUTION) {
|
||||
y = -B * (D + C * z) * denom;
|
||||
x = -A * (D + C * z) * denom;
|
||||
if (evaluateIsZero(x, y, z)) {
|
||||
addPoint(boundsInfo, bounds, x, y, z);
|
||||
}
|
||||
}
|
||||
// Check the solution on the other side of the x-y plane
|
||||
z = -z;
|
||||
insideValue = A * A + B * B - D * D - z * z - 2.0 * C * D * z;
|
||||
if (Math.abs(insideValue) < MINIMUM_RESOLUTION) {
|
||||
y = -B * (D + C * z) * denom;
|
||||
x = -A * (D + C * z) * denom;
|
||||
if (evaluateIsZero(x, y, z)) {
|
||||
addPoint(boundsInfo, bounds, x, y, z);
|
||||
}
|
||||
}
|
||||
} else if (sqrtValue > 0.0) {
|
||||
//System.err.println(" Two latitude solutions");
|
||||
double sqrtResult = Math.sqrt(sqrtValue);
|
||||
|
||||
double insideValue;
|
||||
double sqrtTerm;
|
||||
|
||||
z = D * C + sqrtResult;
|
||||
//System.out.println("z= "+z+" D-C*z = " + (D-C*z) + " Math.sqrt(1.0 - z*z - C*C + z*z*C*C) = "+(Math.sqrt(1.0 - z*z - C*C + z*z*C*C)));
|
||||
// Since we squared both sides of the equation, we may have introduced spurios solutions, so we have to check.
|
||||
// But the same check applies to BOTH solutions -- the +z one as well as the -z one.
|
||||
insideValue = A * A + B * B - D * D - z * z - 2.0 * C * D * z;
|
||||
//System.err.println(" z="+z+" C="+C+" D="+D+" inside value "+insideValue);
|
||||
if (Math.abs(insideValue) < MINIMUM_RESOLUTION) {
|
||||
y = -B * (D + C * z) * denom;
|
||||
x = -A * (D + C * z) * denom;
|
||||
if (evaluateIsZero(x, y, z)) {
|
||||
addPoint(boundsInfo, bounds, x, y, z);
|
||||
}
|
||||
}
|
||||
// Check the solution on the other side of the x-y plane
|
||||
z = -z;
|
||||
insideValue = A * A + B * B - D * D - z * z - 2.0 * C * D * z;
|
||||
//System.err.println(" z="+z+" C="+C+" D="+D+" inside value "+insideValue);
|
||||
if (Math.abs(insideValue) < MINIMUM_RESOLUTION) {
|
||||
y = -B * (D + C * z) * denom;
|
||||
x = -A * (D + C * z) * denom;
|
||||
if (evaluateIsZero(x, y, z)) {
|
||||
addPoint(boundsInfo, bounds, x, y, z);
|
||||
}
|
||||
}
|
||||
z = D * C - sqrtResult;
|
||||
//System.out.println("z= "+z+" D-C*z = " + (D-C*z) + " Math.sqrt(1.0 - z*z - C*C + z*z*C*C) = "+(Math.sqrt(1.0 - z*z - C*C + z*z*C*C)));
|
||||
// Since we squared both sides of the equation, we may have introduced spurios solutions, so we have to check.
|
||||
// But the same check applies to BOTH solutions -- the +z one as well as the -z one.
|
||||
insideValue = A * A + B * B - D * D - z * z - 2.0 * C * D * z;
|
||||
//System.err.println(" z="+z+" C="+C+" D="+D+" inside value "+insideValue);
|
||||
if (Math.abs(insideValue) < MINIMUM_RESOLUTION) {
|
||||
y = -B * (D + C * z) * denom;
|
||||
x = -A * (D + C * z) * denom;
|
||||
if (evaluateIsZero(x, y, z)) {
|
||||
addPoint(boundsInfo, bounds, x, y, z);
|
||||
}
|
||||
}
|
||||
// Check the solution on the other side of the x-y plane
|
||||
z = -z;
|
||||
insideValue = A * A + B * B - D * D - z * z - 2.0 * C * D * z;
|
||||
//System.err.println(" z="+z+" C="+C+" D="+D+" inside value "+insideValue);
|
||||
if (Math.abs(insideValue) < MINIMUM_RESOLUTION) {
|
||||
y = -B * (D + C * z) * denom;
|
||||
x = -A * (D + C * z) * denom;
|
||||
if (evaluateIsZero(x, y, z)) {
|
||||
addPoint(boundsInfo, bounds, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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);
|
||||
for (final GeoPoint point : points) {
|
||||
addPoint(boundsInfo, bounds, point.x, point.y, point.z);
|
||||
}
|
||||
} else {
|
||||
// Horizontal circle.
|
||||
// Since the recordBounds() method will be called ONLY for planes that constitute edges of a shape,
|
||||
// we can be sure that some part of the horizontal circle will be part of the boundary, so we don't need
|
||||
// to check Membership objects.
|
||||
boundsInfo.addHorizontalCircle(-D * C);
|
||||
// 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));
|
||||
}
|
||||
//System.err.println("Done latitude bounds");
|
||||
}
|
||||
|
@ -697,8 +529,8 @@ public class Plane extends Vector {
|
|||
// Geometrically, we have a line segment in x-y space. We need to locate the endpoints
|
||||
// of that line. But luckily, we know some things: specifically, since it is a
|
||||
// degenerate situation in projection, the C value had to have been 0. That
|
||||
// means that our line's endpoints will coincide with the unit circle. All we
|
||||
// need to do then is to find the intersection of the unit circle and the line
|
||||
// means that our line's endpoints will coincide with the projected ellipse. All we
|
||||
// need to do then is to find the intersection of the projected ellipse and the line
|
||||
// equation:
|
||||
//
|
||||
// A x + B y + D = 0
|
||||
|
@ -706,20 +538,20 @@ public class Plane extends Vector {
|
|||
// Since A != 0:
|
||||
// x = (-By - D)/A
|
||||
//
|
||||
// The unit circle:
|
||||
// x^2 + y^2 - 1 = 0
|
||||
// The projected ellipse:
|
||||
// x^2/a^2 + y^2/b^2 - 1 = 0
|
||||
// Substitute:
|
||||
// [(-By-D)/A]^2 + y^2 -1 = 0
|
||||
// [(-By-D)/A]^2/a^2 + y^2/b^2 -1 = 0
|
||||
// Multiply through by A^2:
|
||||
// [-By - D]^2 + A^2*y^2 - A^2 = 0
|
||||
// [-By - D]^2/a^2 + A^2*y^2/b^2 - A^2 = 0
|
||||
// Multiply out:
|
||||
// B^2*y^2 + 2BDy + D^2 + A^2*y^2 - A^2 = 0
|
||||
// B^2*y^2/a^2 + 2BDy/a^2 + D^2/a^2 + A^2*y^2/b^2 - A^2 = 0
|
||||
// Group:
|
||||
// y^2 * [B^2 + A^2] + y [2BD] + [D^2-A^2] = 0
|
||||
// y^2 * [B^2/a^2 + A^2/b^2] + y [2BD/a^2] + [D^2/a^2-A^2] = 0
|
||||
|
||||
a = B * B + A * A;
|
||||
b = 2.0 * B * D;
|
||||
c = D * D - A * A;
|
||||
a = B * B * planetModel.inverseAbSquared + A * A * planetModel.inverseAbSquared;
|
||||
b = 2.0 * B * D * planetModel.inverseAbSquared;
|
||||
c = D * D * planetModel.inverseAbSquared - A * A;
|
||||
|
||||
double sqrtClause = b * b - 4.0 * a * c;
|
||||
|
||||
|
@ -750,9 +582,9 @@ public class Plane extends Vector {
|
|||
// Use equation suitable for B != 0
|
||||
// Since I != 0, we rewrite:
|
||||
// y = (-Ax - D)/B
|
||||
a = B * B + A * A;
|
||||
b = 2.0 * A * D;
|
||||
c = D * D - B * B;
|
||||
a = B * B * planetModel.inverseAbSquared + A * A * planetModel.inverseAbSquared;
|
||||
b = 2.0 * A * D * planetModel.inverseAbSquared;
|
||||
c = D * D * planetModel.inverseAbSquared - B * B;
|
||||
|
||||
double sqrtClause = b * b - 4.0 * a * c;
|
||||
|
||||
|
@ -786,25 +618,25 @@ public class Plane extends Vector {
|
|||
// They are for lat/lon calculation purposes only. x-y is meant to be used for longitude determination,
|
||||
// and z for latitude, and that's all the values are good for.
|
||||
|
||||
// (1) Intersect the plane and the unit sphere, and project the results into the x-y plane:
|
||||
// (1) Intersect the plane and the ellipsoid, and project the results into the x-y plane:
|
||||
// From plane:
|
||||
// z = (-Ax - By - D) / C
|
||||
// From unit sphere:
|
||||
// x^2 + y^2 + [(-Ax - By - D) / C]^2 = 1
|
||||
// From ellipsoid:
|
||||
// x^2/a^2 + y^2/b^2 + [(-Ax - By - D) / C]^2/c^2 = 1
|
||||
// Simplify/expand:
|
||||
// C^2*x^2 + C^2*y^2 + (-Ax - By - D)^2 = C^2
|
||||
// C^2*x^2/a^2 + C^2*y^2/b^2 + (-Ax - By - D)^2/c^2 = C^2
|
||||
//
|
||||
// x^2 * C^2 + y^2 * C^2 + x^2 * (A^2 + ABxy + ADx) + (ABxy + y^2 * B^2 + BDy) + (ADx + BDy + D^2) = C^2
|
||||
// x^2 * C^2/a^2 + y^2 * C^2/b^2 + x^2 * A^2/c^2 + ABxy/c^2 + ADx/c^2 + ABxy/c^2 + y^2 * B^2/c^2 + BDy/c^2 + ADx/c^2 + BDy/c^2 + D^2/c^2 = C^2
|
||||
// Group:
|
||||
// [A^2 + C^2] x^2 + [B^2 + C^2] y^2 + [2AB]xy + [2AD]x + [2BD]y + [D^2-C^2] = 0
|
||||
// [A^2/c^2 + C^2/a^2] x^2 + [B^2/c^2 + C^2/b^2] y^2 + [2AB/c^2]xy + [2AD/c^2]x + [2BD/c^2]y + [D^2/c^2-C^2] = 0
|
||||
// For convenience, introduce post-projection coefficient variables to make life easier.
|
||||
// E x^2 + F y^2 + G xy + H x + I y + J = 0
|
||||
double E = A * A + C * C;
|
||||
double F = B * B + C * C;
|
||||
double G = 2.0 * A * B;
|
||||
double H = 2.0 * A * D;
|
||||
double I = 2.0 * B * D;
|
||||
double J = D * D - C * C;
|
||||
double E = A * A * planetModel.inverseCSquared + C * C * planetModel.inverseAbSquared;
|
||||
double F = B * B * planetModel.inverseCSquared + C * C * planetModel.inverseAbSquared;
|
||||
double G = 2.0 * A * B * planetModel.inverseCSquared;
|
||||
double H = 2.0 * A * D * planetModel.inverseCSquared;
|
||||
double I = 2.0 * B * D * planetModel.inverseCSquared;
|
||||
double J = D * D * planetModel.inverseCSquared - C * C;
|
||||
|
||||
//System.err.println("E = " + E + " F = " + F + " G = " + G + " H = "+ H + " I = " + I + " J = " + J);
|
||||
|
||||
|
@ -962,6 +794,7 @@ public class Plane extends Vector {
|
|||
* Determine whether the plane intersects another plane within the
|
||||
* bounds provided.
|
||||
*
|
||||
* @param planetModel is the planet model to use in determining intersection.
|
||||
* @param q is the other plane.
|
||||
* @param notablePoints are points to look at to disambiguate cases when the two planes are identical.
|
||||
* @param moreNotablePoints are additional points to look at to disambiguate cases when the two planes are identical.
|
||||
|
@ -969,7 +802,7 @@ public class Plane extends Vector {
|
|||
* @param moreBounds are more bounds.
|
||||
* @return true if there's an intersection.
|
||||
*/
|
||||
public boolean intersects(final Plane q, final GeoPoint[] notablePoints, final GeoPoint[] moreNotablePoints, final Membership[] bounds, final Membership... moreBounds) {
|
||||
public boolean intersects(final PlanetModel planetModel, final Plane q, final GeoPoint[] notablePoints, final GeoPoint[] moreNotablePoints, final Membership[] bounds, final Membership... moreBounds) {
|
||||
//System.err.println("Does plane "+this+" intersect with plane "+q);
|
||||
// If the two planes are identical, then the math will find no points of intersection.
|
||||
// So a special case of this is to check for plane equality. But that is not enough, because
|
||||
|
@ -994,7 +827,7 @@ public class Plane extends Vector {
|
|||
//System.err.println(" no notable points inside found; no intersection");
|
||||
return false;
|
||||
}
|
||||
return findIntersections(q, bounds, moreBounds).length > 0;
|
||||
return findIntersections(planetModel, q, bounds, moreBounds).length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1042,8 +875,8 @@ public class Plane extends Vector {
|
|||
/**
|
||||
* Find a sample point on the intersection between two planes and the unit sphere.
|
||||
*/
|
||||
public GeoPoint getSampleIntersectionPoint(final Plane q) {
|
||||
final GeoPoint[] intersections = findIntersections(q, NO_BOUNDS, NO_BOUNDS);
|
||||
public GeoPoint getSampleIntersectionPoint(final PlanetModel planetModel, final Plane q) {
|
||||
final GeoPoint[] intersections = findIntersections(planetModel, q, NO_BOUNDS, NO_BOUNDS);
|
||||
if (intersections.length == 0)
|
||||
return null;
|
||||
return intersections[0];
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
package org.apache.lucene.spatial.spatial4j.geo3d;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Holds mathematical constants associated with the model of a planet.
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public class PlanetModel {
|
||||
|
||||
/** Planet model corresponding to sphere. */
|
||||
public static final PlanetModel SPHERE = new PlanetModel(1.0,1.0);
|
||||
|
||||
/** Mean radius */
|
||||
public static final double WGS84_MEAN = 6371009.0;
|
||||
/** Polar radius */
|
||||
public static final double WGS84_POLAR = 6356752.3;
|
||||
/** Equatorial radius */
|
||||
public static final double WGS84_EQUATORIAL = 6378137.0;
|
||||
/** Planet model corresponding to WGS84 */
|
||||
public static final PlanetModel WGS84 = new PlanetModel(WGS84_EQUATORIAL/WGS84_MEAN,
|
||||
WGS84_POLAR/WGS84_MEAN);
|
||||
|
||||
// Surface of the planet:
|
||||
// x^2/a^2 + y^2/b^2 + z^2/c^2 = 1.0
|
||||
// Scaling factors are a,b,c. geo3d can only support models where a==b, so use ab instead.
|
||||
public final double ab;
|
||||
public final double c;
|
||||
public final double inverseAb;
|
||||
public final double inverseC;
|
||||
public final double inverseAbSquared;
|
||||
public final double inverseCSquared;
|
||||
// We do NOT include radius, because all computations in geo3d are in radians, not meters.
|
||||
|
||||
// Compute north and south pole for planet model, since these are commonly used.
|
||||
public final GeoPoint NORTH_POLE;
|
||||
public final GeoPoint SOUTH_POLE;
|
||||
|
||||
public PlanetModel(final double ab, final double c) {
|
||||
this.ab = ab;
|
||||
this.c = c;
|
||||
this.inverseAb = 1.0 / ab;
|
||||
this.inverseC = 1.0 / c;
|
||||
this.inverseAbSquared = inverseAb * inverseAb;
|
||||
this.inverseCSquared = inverseC * inverseC;
|
||||
this.NORTH_POLE = new GeoPoint(c, 0.0, 0.0, 1.0);
|
||||
this.SOUTH_POLE = new GeoPoint(c, 0.0, 0.0, -1.0);
|
||||
}
|
||||
|
||||
/** Find the minimum magnitude of all points on the ellipsoid.
|
||||
*/
|
||||
public double getMinimumMagnitude() {
|
||||
return Math.min(this.ab, this.c);
|
||||
}
|
||||
|
||||
/** Find the maximum magnitude of all points on the ellipsoid.
|
||||
*/
|
||||
public double getMaximumMagnitude() {
|
||||
return Math.max(this.ab, this.c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (!(o instanceof PlanetModel))
|
||||
return false;
|
||||
final PlanetModel other = (PlanetModel)o;
|
||||
return ab == other.ab && c == other.c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Double.hashCode(ab) + Double.hashCode(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (this.equals(SPHERE)) {
|
||||
return "PlanetModel.SPHERE";
|
||||
} else if (this.equals(WGS84)) {
|
||||
return "PlanetModel.WGS84";
|
||||
} else {
|
||||
return "PlanetModel(ab="+ab+" c="+c+")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -53,10 +53,11 @@ public class SidedPlane extends Plane implements Membership {
|
|||
* Construct a sided plane from a point and a Z coordinate.
|
||||
*
|
||||
* @param p point to evaluate.
|
||||
* @param height is the Z coordinate of the plane.
|
||||
* @param planetModel is the planet model.
|
||||
* @param sinLat is the sin of the latitude of the plane.
|
||||
*/
|
||||
public SidedPlane(Vector p, double height) {
|
||||
super(height);
|
||||
public SidedPlane(Vector p, final PlanetModel planetModel, double sinLat) {
|
||||
super(planetModel, sinLat);
|
||||
sigNum = Math.signum(evaluate(p));
|
||||
}
|
||||
|
||||
|
@ -84,6 +85,28 @@ public class SidedPlane extends Plane implements Membership {
|
|||
sigNum = Math.signum(evaluate(p));
|
||||
}
|
||||
|
||||
/** Construct a sided plane from two points and a third normal vector.
|
||||
*/
|
||||
public static SidedPlane constructNormalizedPerpendicularSidedPlane(final Vector insidePoint,
|
||||
final Vector normalVector, final Vector point1, final Vector point2) {
|
||||
final Vector pointsVector = new Vector(point1.x - point2.x, point1.y - point2.y, point1.z - point2.z);
|
||||
final Vector newNormalVector = new Vector(normalVector, pointsVector).normalize();
|
||||
// To construct the plane, we now just need D, which is simply the negative of the evaluation of the circle normal vector at one of the points.
|
||||
return new SidedPlane(insidePoint, newNormalVector, -newNormalVector.dotProduct(point1));
|
||||
}
|
||||
|
||||
/** Construct a sided plane from three points.
|
||||
*/
|
||||
public static SidedPlane constructNormalizedThreePointSidedPlane(final Vector insidePoint,
|
||||
final Vector point1, final Vector point2, final Vector point3) {
|
||||
final Vector planeNormal = new Vector(
|
||||
new Vector(point1.x - point2.x, point1.y - point2.y, point1.z - point2.z),
|
||||
new Vector(point2.x - point3.x, point2.y - point3.y, point2.z - point3.z)).normalize();
|
||||
if (planeNormal == null)
|
||||
return null;
|
||||
return new SidedPlane(insidePoint, planeNormal, -planeNormal.dotProduct(point2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a point is within this shape.
|
||||
*
|
||||
|
|
|
@ -114,14 +114,20 @@ public class Vector {
|
|||
*/
|
||||
public boolean isWithin(final Membership[] bounds, final Membership[] moreBounds) {
|
||||
// Return true if the point described is within all provided bounds
|
||||
//System.err.println(" checking if "+this+" is within bounds");
|
||||
for (Membership bound : bounds) {
|
||||
if (bound != null && !bound.isWithin(this))
|
||||
if (bound != null && !bound.isWithin(this)) {
|
||||
//System.err.println(" NOT within "+bound);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (Membership bound : moreBounds) {
|
||||
if (bound != null && !bound.isWithin(this))
|
||||
if (bound != null && !bound.isWithin(this)) {
|
||||
//System.err.println(" NOT within "+bound);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//System.err.println(" is within");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -301,6 +307,20 @@ public class Vector {
|
|||
return Math.sqrt(x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
/** Compute the magnitude of a vector projected to a given
|
||||
* planet model.
|
||||
*/
|
||||
protected static double computeMagnitude(final PlanetModel planetModel, final double x, final double y, final double z) {
|
||||
return 1.0 / Math.sqrt(x*x*planetModel.inverseAbSquared + y*y*planetModel.inverseAbSquared + z*z*planetModel.inverseCSquared);
|
||||
}
|
||||
|
||||
/** Compute the magnitude of a vector projected to a given
|
||||
* planet model.
|
||||
*/
|
||||
protected static double computeMagnitude(final PlanetModel planetModel, final double z) {
|
||||
return 1.0 / Math.sqrt((1.0-z*z)*planetModel.inverseAbSquared + z*z*planetModel.inverseCSquared);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Vector))
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.apache.lucene.spatial.spatial4j.geo3d.GeoPath;
|
|||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoPoint;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoPolygonFactory;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoShape;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.PlanetModel;
|
||||
import org.junit.Test;
|
||||
|
||||
import static com.spatial4j.core.distance.DistanceUtils.DEGREES_TO_RADIANS;
|
||||
|
@ -81,12 +82,12 @@ public class Geo3dRptTest extends RandomSpatialOpStrategyTestCase {
|
|||
public void testFailure1() throws IOException {
|
||||
setupStrategy();
|
||||
final List<GeoPoint> points = new ArrayList<GeoPoint>();
|
||||
points.add(new GeoPoint(18 * DEGREES_TO_RADIANS, -27 * DEGREES_TO_RADIANS));
|
||||
points.add(new GeoPoint(-57 * DEGREES_TO_RADIANS, 146 * DEGREES_TO_RADIANS));
|
||||
points.add(new GeoPoint(14 * DEGREES_TO_RADIANS, -180 * DEGREES_TO_RADIANS));
|
||||
points.add(new GeoPoint(-15 * DEGREES_TO_RADIANS, 153 * DEGREES_TO_RADIANS));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, 18 * DEGREES_TO_RADIANS, -27 * DEGREES_TO_RADIANS));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, -57 * DEGREES_TO_RADIANS, 146 * DEGREES_TO_RADIANS));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, 14 * DEGREES_TO_RADIANS, -180 * DEGREES_TO_RADIANS));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, -15 * DEGREES_TO_RADIANS, 153 * DEGREES_TO_RADIANS));
|
||||
|
||||
final Shape triangle = new Geo3dShape(GeoPolygonFactory.makeGeoPolygon(points,0),ctx);
|
||||
final Shape triangle = new Geo3dShape(GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points,0),ctx);
|
||||
final Rectangle rect = ctx.makeRectangle(-49, -45, 73, 86);
|
||||
testOperation(rect,SpatialOperation.Intersects,triangle, false);
|
||||
}
|
||||
|
@ -101,11 +102,11 @@ public class Geo3dRptTest extends RandomSpatialOpStrategyTestCase {
|
|||
|
||||
private Shape makeTriangle(double x1, double y1, double x2, double y2, double x3, double y3) {
|
||||
final List<GeoPoint> geoPoints = new ArrayList<>();
|
||||
geoPoints.add(new GeoPoint(y1 * DEGREES_TO_RADIANS, x1 * DEGREES_TO_RADIANS));
|
||||
geoPoints.add(new GeoPoint(y2 * DEGREES_TO_RADIANS, x2 * DEGREES_TO_RADIANS));
|
||||
geoPoints.add(new GeoPoint(y3 * DEGREES_TO_RADIANS, x3 * DEGREES_TO_RADIANS));
|
||||
geoPoints.add(new GeoPoint(PlanetModel.SPHERE, y1 * DEGREES_TO_RADIANS, x1 * DEGREES_TO_RADIANS));
|
||||
geoPoints.add(new GeoPoint(PlanetModel.SPHERE, y2 * DEGREES_TO_RADIANS, x2 * DEGREES_TO_RADIANS));
|
||||
geoPoints.add(new GeoPoint(PlanetModel.SPHERE, y3 * DEGREES_TO_RADIANS, x3 * DEGREES_TO_RADIANS));
|
||||
final int convexPointIndex = 0;
|
||||
final GeoShape shape = GeoPolygonFactory.makeGeoPolygon(geoPoints, convexPointIndex);
|
||||
final GeoShape shape = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, geoPoints, convexPointIndex);
|
||||
return new Geo3dShape(shape, ctx);
|
||||
}
|
||||
|
||||
|
@ -125,12 +126,12 @@ public class Geo3dRptTest extends RandomSpatialOpStrategyTestCase {
|
|||
final List<GeoPoint> geoPoints = new ArrayList<>();
|
||||
while (geoPoints.size() < vertexCount) {
|
||||
final Point point = randomPoint();
|
||||
final GeoPoint gPt = new GeoPoint(point.getY() * DEGREES_TO_RADIANS, point.getX() * DEGREES_TO_RADIANS);
|
||||
final GeoPoint gPt = new GeoPoint(PlanetModel.SPHERE, point.getY() * DEGREES_TO_RADIANS, point.getX() * DEGREES_TO_RADIANS);
|
||||
geoPoints.add(gPt);
|
||||
}
|
||||
final int convexPointIndex = random().nextInt(vertexCount); //If we get this wrong, hopefully we get IllegalArgumentException
|
||||
try {
|
||||
final GeoShape shape = GeoPolygonFactory.makeGeoPolygon(geoPoints, convexPointIndex);
|
||||
final GeoShape shape = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, geoPoints, convexPointIndex);
|
||||
return new Geo3dShape(shape, ctx);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// This is what happens when we create a shape that is invalid. Although it is conceivable that there are cases where
|
||||
|
@ -145,7 +146,7 @@ public class Geo3dRptTest extends RandomSpatialOpStrategyTestCase {
|
|||
final int circleRadius = random().nextInt(179) + 1;
|
||||
final Point point = randomPoint();
|
||||
try {
|
||||
final GeoShape shape = new GeoCircle(point.getY() * DEGREES_TO_RADIANS, point.getX() * DEGREES_TO_RADIANS,
|
||||
final GeoShape shape = new GeoCircle(PlanetModel.SPHERE, point.getY() * DEGREES_TO_RADIANS, point.getX() * DEGREES_TO_RADIANS,
|
||||
circleRadius * DEGREES_TO_RADIANS);
|
||||
return new Geo3dShape(shape, ctx);
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -167,7 +168,7 @@ public class Geo3dRptTest extends RandomSpatialOpStrategyTestCase {
|
|||
lrhcPoint = temp;
|
||||
}
|
||||
try {
|
||||
final GeoShape shape = GeoBBoxFactory.makeGeoBBox(ulhcPoint.getY() * DEGREES_TO_RADIANS,
|
||||
final GeoShape shape = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, ulhcPoint.getY() * DEGREES_TO_RADIANS,
|
||||
lrhcPoint.getY() * DEGREES_TO_RADIANS,
|
||||
ulhcPoint.getX() * DEGREES_TO_RADIANS,
|
||||
lrhcPoint.getX() * DEGREES_TO_RADIANS);
|
||||
|
@ -186,7 +187,7 @@ public class Geo3dRptTest extends RandomSpatialOpStrategyTestCase {
|
|||
final double width = (random().nextInt(89)+1) * DEGREES_TO_RADIANS;
|
||||
while (true) {
|
||||
try {
|
||||
final GeoPath path = new GeoPath(width);
|
||||
final GeoPath path = new GeoPath(PlanetModel.SPHERE, width);
|
||||
for (int i = 0; i < pointCount; i++) {
|
||||
final Point nextPoint = randomPoint();
|
||||
path.addPoint(nextPoint.getY() * DEGREES_TO_RADIANS, nextPoint.getX() * DEGREES_TO_RADIANS);
|
||||
|
|
|
@ -25,9 +25,7 @@ import com.carrotsearch.randomizedtesting.RandomizedContext;
|
|||
import com.spatial4j.core.context.SpatialContext;
|
||||
import com.spatial4j.core.distance.DistanceUtils;
|
||||
import com.spatial4j.core.shape.Point;
|
||||
import com.spatial4j.core.shape.Rectangle;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.Bounds;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoArea;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoBBox;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoBBoxFactory;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoCircle;
|
||||
|
@ -35,26 +33,30 @@ import org.apache.lucene.spatial.spatial4j.geo3d.GeoPath;
|
|||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoPoint;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoPolygonFactory;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoShape;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.PlanetModel;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import static com.spatial4j.core.distance.DistanceUtils.DEGREES_TO_RADIANS;
|
||||
|
||||
public class Geo3dShapeRectRelationTest extends RandomizedShapeTestCase {
|
||||
public abstract class Geo3dShapeRectRelationTestCase extends RandomizedShapeTestCase {
|
||||
protected final static double RADIANS_PER_DEGREE = Math.PI/180.0;
|
||||
|
||||
@Rule
|
||||
public final LogRule testLog = LogRule.instance;
|
||||
|
||||
static Random random() {
|
||||
protected static Random random() {
|
||||
return RandomizedContext.current().getRandom();
|
||||
}
|
||||
|
||||
{
|
||||
ctx = SpatialContext.GEO;
|
||||
protected final PlanetModel planetModel;
|
||||
|
||||
public Geo3dShapeRectRelationTestCase(PlanetModel planetModel) {
|
||||
super(SpatialContext.GEO);
|
||||
this.planetModel = planetModel;
|
||||
}
|
||||
|
||||
protected final static double RADIANS_PER_DEGREE = Math.PI/180.0;
|
||||
|
||||
protected static GeoBBox getBoundingBox(final GeoShape path) {
|
||||
protected GeoBBox getBoundingBox(final GeoShape path) {
|
||||
Bounds bounds = path.getBounds(null);
|
||||
|
||||
double leftLon;
|
||||
|
@ -78,7 +80,7 @@ public class Geo3dShapeRectRelationTest extends RandomizedShapeTestCase {
|
|||
} else {
|
||||
maxLat = bounds.getMaxLatitude().doubleValue();
|
||||
}
|
||||
return GeoBBoxFactory.makeGeoBBox(maxLat, minLat, leftLon, rightLon);
|
||||
return GeoBBoxFactory.makeGeoBBox(planetModel, maxLat, minLat, leftLon, rightLon);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -91,9 +93,9 @@ public class Geo3dShapeRectRelationTest extends RandomizedShapeTestCase {
|
|||
final int circleRadius = random().nextInt(179) + 1;//no 0-radius
|
||||
final Point point = nearP;
|
||||
try {
|
||||
final GeoShape shape = new GeoCircle(point.getY() * DEGREES_TO_RADIANS, point.getX() * DEGREES_TO_RADIANS,
|
||||
final GeoShape shape = new GeoCircle(planetModel, point.getY() * DEGREES_TO_RADIANS, point.getX() * DEGREES_TO_RADIANS,
|
||||
circleRadius * DEGREES_TO_RADIANS);
|
||||
return new Geo3dShape(shape, ctx);
|
||||
return new Geo3dShape(planetModel, shape, ctx);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// This is what happens when we create a shape that is invalid. Although it is conceivable that there are cases where
|
||||
// the exception is thrown incorrectly, we aren't going to be able to do that in this random test.
|
||||
|
@ -131,11 +133,11 @@ public class Geo3dShapeRectRelationTest extends RandomizedShapeTestCase {
|
|||
ulhcPoint = lrhcPoint;
|
||||
lrhcPoint = temp;
|
||||
}
|
||||
final GeoShape shape = GeoBBoxFactory.makeGeoBBox(ulhcPoint.getY() * DEGREES_TO_RADIANS,
|
||||
final GeoShape shape = GeoBBoxFactory.makeGeoBBox(planetModel, ulhcPoint.getY() * DEGREES_TO_RADIANS,
|
||||
lrhcPoint.getY() * DEGREES_TO_RADIANS,
|
||||
ulhcPoint.getX() * DEGREES_TO_RADIANS,
|
||||
lrhcPoint.getX() * DEGREES_TO_RADIANS);
|
||||
return new Geo3dShape(shape, ctx);
|
||||
return new Geo3dShape(planetModel, shape, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -160,13 +162,13 @@ public class Geo3dShapeRectRelationTest extends RandomizedShapeTestCase {
|
|||
final Point point = randomPoint();
|
||||
if (ctx.getDistCalc().distance(point,centerPoint) > maxDistance)
|
||||
continue;
|
||||
final GeoPoint gPt = new GeoPoint(point.getY() * DEGREES_TO_RADIANS, point.getX() * DEGREES_TO_RADIANS);
|
||||
final GeoPoint gPt = new GeoPoint(planetModel, point.getY() * DEGREES_TO_RADIANS, point.getX() * DEGREES_TO_RADIANS);
|
||||
geoPoints.add(gPt);
|
||||
}
|
||||
final int convexPointIndex = random().nextInt(vertexCount); //If we get this wrong, hopefully we get IllegalArgumentException
|
||||
try {
|
||||
final GeoShape shape = GeoPolygonFactory.makeGeoPolygon(geoPoints, convexPointIndex);
|
||||
return new Geo3dShape(shape, ctx);
|
||||
final GeoShape shape = GeoPolygonFactory.makeGeoPolygon(planetModel, geoPoints, convexPointIndex);
|
||||
return new Geo3dShape(planetModel, shape, ctx);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// This is what happens when we create a shape that is invalid. Although it is conceivable that there are cases where
|
||||
// the exception is thrown incorrectly, we aren't going to be able to do that in this random test.
|
||||
|
@ -201,7 +203,7 @@ public class Geo3dShapeRectRelationTest extends RandomizedShapeTestCase {
|
|||
final double width = (random().nextInt(89)+1) * DEGREES_TO_RADIANS;
|
||||
while (true) {
|
||||
try {
|
||||
final GeoPath path = new GeoPath(width);
|
||||
final GeoPath path = new GeoPath(planetModel, width);
|
||||
int i = 0;
|
||||
while (i < pointCount) {
|
||||
final Point nextPoint = randomPoint();
|
||||
|
@ -211,7 +213,7 @@ public class Geo3dShapeRectRelationTest extends RandomizedShapeTestCase {
|
|||
i++;
|
||||
}
|
||||
path.done();
|
||||
return new Geo3dShape(path, ctx);
|
||||
return new Geo3dShape(planetModel, path, ctx);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// This is what happens when we create a shape that is invalid. Although it is conceivable that there are cases where
|
||||
// the exception is thrown incorrectly, we aren't going to be able to do that in this random test.
|
||||
|
@ -238,38 +240,4 @@ public class Geo3dShapeRectRelationTest extends RandomizedShapeTestCase {
|
|||
return ctx.makePoint(geoPoint.x * DistanceUtils.RADIANS_TO_DEGREES,
|
||||
geoPoint.y * DistanceUtils.RADIANS_TO_DEGREES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure1() {
|
||||
final GeoBBox rect = GeoBBoxFactory.makeGeoBBox(88 * RADIANS_PER_DEGREE, 30 * RADIANS_PER_DEGREE, -30 * RADIANS_PER_DEGREE, 62 * RADIANS_PER_DEGREE);
|
||||
final List<GeoPoint> points = new ArrayList<GeoPoint>();
|
||||
points.add(new GeoPoint(66.2465299717 * RADIANS_PER_DEGREE, -29.1786158537 * RADIANS_PER_DEGREE));
|
||||
points.add(new GeoPoint(43.684447915 * RADIANS_PER_DEGREE, 46.2210986329 * RADIANS_PER_DEGREE));
|
||||
points.add(new GeoPoint(30.4579218227 * RADIANS_PER_DEGREE, 14.5238410082 * RADIANS_PER_DEGREE));
|
||||
final GeoShape path = GeoPolygonFactory.makeGeoPolygon(points,0);
|
||||
|
||||
final GeoPoint point = new GeoPoint(34.2730264413182 * RADIANS_PER_DEGREE, 82.75500168892472 * RADIANS_PER_DEGREE);
|
||||
|
||||
// Apparently the rectangle thinks the polygon is completely within it... "shape inside rectangle"
|
||||
assertTrue(GeoArea.WITHIN == rect.getRelationship(path));
|
||||
|
||||
// Point is within path? Apparently not...
|
||||
assertFalse(path.isWithin(point));
|
||||
|
||||
// If it is within the path, it must be within the rectangle, and similarly visa versa
|
||||
assertFalse(rect.isWithin(point));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure2_LUCENE6475() {
|
||||
GeoShape geo3dCircle = new GeoCircle(1.6282053147165243E-4 * RADIANS_PER_DEGREE,
|
||||
-70.1600629789353 * RADIANS_PER_DEGREE, 86 * RADIANS_PER_DEGREE);
|
||||
Geo3dShape geo3dShape = new Geo3dShape(geo3dCircle, ctx);
|
||||
Rectangle rect = ctx.makeRectangle(-118, -114, -2.0, 32.0);
|
||||
assertTrue(geo3dShape.relate(rect).intersects());
|
||||
// thus the bounding box must intersect too
|
||||
assertTrue(geo3dShape.getBoundingBox().relate(rect).intersects());
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package org.apache.lucene.spatial.spatial4j;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.spatial4j.core.shape.Rectangle;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoArea;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoBBox;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoBBoxFactory;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoCircle;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoPoint;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoPolygonFactory;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoShape;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.PlanetModel;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Geo3dShapeSphereModelRectRelationTest extends Geo3dShapeRectRelationTestCase {
|
||||
|
||||
public Geo3dShapeSphereModelRectRelationTest() {
|
||||
super(PlanetModel.SPHERE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure1() {
|
||||
final GeoBBox rect = GeoBBoxFactory.makeGeoBBox(planetModel, 88 * RADIANS_PER_DEGREE, 30 * RADIANS_PER_DEGREE, -30 * RADIANS_PER_DEGREE, 62 * RADIANS_PER_DEGREE);
|
||||
final List<GeoPoint> points = new ArrayList<>();
|
||||
points.add(new GeoPoint(planetModel, 66.2465299717 * RADIANS_PER_DEGREE, -29.1786158537 * RADIANS_PER_DEGREE));
|
||||
points.add(new GeoPoint(planetModel, 43.684447915 * RADIANS_PER_DEGREE, 46.2210986329 * RADIANS_PER_DEGREE));
|
||||
points.add(new GeoPoint(planetModel, 30.4579218227 * RADIANS_PER_DEGREE, 14.5238410082 * RADIANS_PER_DEGREE));
|
||||
final GeoShape path = GeoPolygonFactory.makeGeoPolygon(planetModel, points,0);
|
||||
|
||||
final GeoPoint point = new GeoPoint(planetModel, 34.2730264413182 * RADIANS_PER_DEGREE, 82.75500168892472 * RADIANS_PER_DEGREE);
|
||||
|
||||
// Apparently the rectangle thinks the polygon is completely within it... "shape inside rectangle"
|
||||
assertTrue(GeoArea.WITHIN == rect.getRelationship(path));
|
||||
|
||||
// Point is within path? Apparently not...
|
||||
assertFalse(path.isWithin(point));
|
||||
|
||||
// If it is within the path, it must be within the rectangle, and similarly visa versa
|
||||
assertFalse(rect.isWithin(point));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure2_LUCENE6475() {
|
||||
GeoShape geo3dCircle = new GeoCircle(planetModel, 1.6282053147165243E-4 * RADIANS_PER_DEGREE,
|
||||
-70.1600629789353 * RADIANS_PER_DEGREE, 86 * RADIANS_PER_DEGREE);
|
||||
Geo3dShape geo3dShape = new Geo3dShape(planetModel, geo3dCircle, ctx);
|
||||
Rectangle rect = ctx.makeRectangle(-118, -114, -2.0, 32.0);
|
||||
assertTrue(geo3dShape.relate(rect).intersects());
|
||||
// thus the bounding box must intersect too
|
||||
assertTrue(geo3dShape.getBoundingBox().relate(rect).intersects());
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package org.apache.lucene.spatial.spatial4j;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoArea;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoBBox;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoBBoxFactory;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoCircle;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoPath;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoPoint;
|
||||
import org.apache.lucene.spatial.spatial4j.geo3d.PlanetModel;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Geo3dShapeWGS84ModelRectRelationTest extends Geo3dShapeRectRelationTestCase {
|
||||
|
||||
public Geo3dShapeWGS84ModelRectRelationTest() {
|
||||
super(PlanetModel.WGS84);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure1() {
|
||||
final GeoBBox rect = GeoBBoxFactory.makeGeoBBox(planetModel, 90 * RADIANS_PER_DEGREE, 74 * RADIANS_PER_DEGREE,
|
||||
40 * RADIANS_PER_DEGREE, 60 * RADIANS_PER_DEGREE);
|
||||
final GeoPath path = new GeoPath(planetModel, 4 * RADIANS_PER_DEGREE);
|
||||
path.addPoint(84.4987594274 * RADIANS_PER_DEGREE, -22.8345484402 * RADIANS_PER_DEGREE);
|
||||
path.done();
|
||||
assertTrue(GeoArea.DISJOINT == rect.getRelationship(path));
|
||||
// This is what the test failure claimed...
|
||||
//assertTrue(GeoArea.CONTAINS == rect.getRelationship(path));
|
||||
//final GeoBBox bbox = getBoundingBox(path);
|
||||
//assertFalse(GeoArea.DISJOINT == rect.getRelationship(bbox));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure2() {
|
||||
final GeoBBox rect = GeoBBoxFactory.makeGeoBBox(planetModel, -74 * RADIANS_PER_DEGREE, -90 * RADIANS_PER_DEGREE,
|
||||
0 * RADIANS_PER_DEGREE, 26 * RADIANS_PER_DEGREE);
|
||||
final GeoCircle circle = new GeoCircle(planetModel, -87.3647352103 * RADIANS_PER_DEGREE, 52.3769709972 * RADIANS_PER_DEGREE, 1 * RADIANS_PER_DEGREE);
|
||||
assertTrue(GeoArea.DISJOINT == rect.getRelationship(circle));
|
||||
// This is what the test failure claimed...
|
||||
//assertTrue(GeoArea.CONTAINS == rect.getRelationship(circle));
|
||||
//final GeoBBox bbox = getBoundingBox(circle);
|
||||
//assertFalse(GeoArea.DISJOINT == rect.getRelationship(bbox));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure3() {
|
||||
/*
|
||||
[junit4] 1> S-R Rel: {}, Shape {}, Rectangle {} lap# {} [CONTAINS, Geo3dShape{planetmodel=PlanetModel: {ab=1.0011188180710464, c=0.9977622539852008}, shape=GeoPath: {planetmodel=PlanetModel: {ab=1.0011188180710464, c=0.9977622539852008}, width=1.53588974175501(87.99999999999999),
|
||||
points={[[X=0.12097657665150223, Y=-0.6754177666095532, Z=0.7265376136709238], [X=-0.3837892785614207, Y=0.4258049113530899, Z=0.8180007850434892]]}}},
|
||||
Rect(minX=4.0,maxX=36.0,minY=16.0,maxY=16.0), 6981](no slf4j subst; sorry)
|
||||
[junit4] FAILURE 0.59s | Geo3dWGS84ShapeRectRelationTest.testGeoPathRect <<<
|
||||
[junit4] > Throwable #1: java.lang.AssertionError: Geo3dShape{planetmodel=PlanetModel: {ab=1.0011188180710464, c=0.9977622539852008}, shape=GeoPath: {planetmodel=PlanetModel: {ab=1.0011188180710464, c=0.9977622539852008}, width=1.53588974175501(87.99999999999999),
|
||||
points={[[X=0.12097657665150223, Y=-0.6754177666095532, Z=0.7265376136709238], [X=-0.3837892785614207, Y=0.4258049113530899, Z=0.8180007850434892]]}}} intersect Pt(x=23.81626064835212,y=16.0)
|
||||
[junit4] > at __randomizedtesting.SeedInfo.seed([2595268DA3F13FEA:6CC30D8C83453E5D]:0)
|
||||
[junit4] > at org.apache.lucene.spatial.spatial4j.RandomizedShapeTestCase._assertIntersect(RandomizedShapeTestCase.java:168)
|
||||
[junit4] > at org.apache.lucene.spatial.spatial4j.RandomizedShapeTestCase.assertRelation(RandomizedShapeTestCase.java:153)
|
||||
[junit4] > at org.apache.lucene.spatial.spatial4j.RectIntersectionTestHelper.testRelateWithRectangle(RectIntersectionTestHelper.java:128)
|
||||
[junit4] > at org.apache.lucene.spatial.spatial4j.Geo3dWGS84ShapeRectRelationTest.testGeoPathRect(Geo3dWGS84ShapeRectRelationTest.java:265)
|
||||
*/
|
||||
final GeoBBox rect = GeoBBoxFactory.makeGeoBBox(planetModel, 16 * RADIANS_PER_DEGREE, 16 * RADIANS_PER_DEGREE, 4 * RADIANS_PER_DEGREE, 36 * RADIANS_PER_DEGREE);
|
||||
final GeoPoint pt = new GeoPoint(planetModel, 16 * RADIANS_PER_DEGREE, 23.81626064835212 * RADIANS_PER_DEGREE);
|
||||
final GeoPath path = new GeoPath(planetModel, 88 * RADIANS_PER_DEGREE);
|
||||
path.addPoint(46.6369060853 * RADIANS_PER_DEGREE, -79.8452213228 * RADIANS_PER_DEGREE);
|
||||
path.addPoint(54.9779334519 * RADIANS_PER_DEGREE, 132.029177424 * RADIANS_PER_DEGREE);
|
||||
path.done();
|
||||
System.out.println("rect=" + rect);
|
||||
// Rectangle is within path (this is wrong; it's on the other side. Should be OVERLAPS)
|
||||
assertTrue(GeoArea.OVERLAPS == rect.getRelationship(path));
|
||||
// Rectangle contains point
|
||||
//assertTrue(rect.isWithin(pt));
|
||||
// Path contains point (THIS FAILS)
|
||||
//assertTrue(path.isWithin(pt));
|
||||
// What happens: (1) The center point of the horizontal line is within the path, in fact within a radius of one of the endpoints.
|
||||
// (2) The point mentioned is NOT inside either SegmentEndpoint.
|
||||
// (3) The point mentioned is NOT inside the path segment, either. (I think it should be...)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -36,14 +36,14 @@ public class GeoBBoxTest {
|
|||
GeoConvexPolygon cp;
|
||||
int relationship;
|
||||
List<GeoPoint> points = new ArrayList<GeoPoint>();
|
||||
points.add(new GeoPoint(24 * DEGREES_TO_RADIANS, -30 * DEGREES_TO_RADIANS));
|
||||
points.add(new GeoPoint(-11 * DEGREES_TO_RADIANS, 101 * DEGREES_TO_RADIANS));
|
||||
points.add(new GeoPoint(-49 * DEGREES_TO_RADIANS, -176 * DEGREES_TO_RADIANS));
|
||||
GeoMembershipShape shape = GeoPolygonFactory.makeGeoPolygon(points, 0);
|
||||
box = GeoBBoxFactory.makeGeoBBox(-64 * DEGREES_TO_RADIANS, -64 * DEGREES_TO_RADIANS, -180 * DEGREES_TO_RADIANS, 180 * DEGREES_TO_RADIANS);
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, 24 * DEGREES_TO_RADIANS, -30 * DEGREES_TO_RADIANS));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, -11 * DEGREES_TO_RADIANS, 101 * DEGREES_TO_RADIANS));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, -49 * DEGREES_TO_RADIANS, -176 * DEGREES_TO_RADIANS));
|
||||
GeoMembershipShape shape = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points, 0);
|
||||
box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, -64 * DEGREES_TO_RADIANS, -64 * DEGREES_TO_RADIANS, -180 * DEGREES_TO_RADIANS, 180 * DEGREES_TO_RADIANS);
|
||||
relationship = box.getRelationship(shape);
|
||||
assertEquals(GeoArea.CONTAINS, relationship);
|
||||
box = GeoBBoxFactory.makeGeoBBox(-61.85 * DEGREES_TO_RADIANS, -67.5 * DEGREES_TO_RADIANS, -180 * DEGREES_TO_RADIANS, -168.75 * DEGREES_TO_RADIANS);
|
||||
box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, -61.85 * DEGREES_TO_RADIANS, -67.5 * DEGREES_TO_RADIANS, -180 * DEGREES_TO_RADIANS, -168.75 * DEGREES_TO_RADIANS);
|
||||
System.out.println("Shape = " + shape + " Rect = " + box);
|
||||
relationship = box.getRelationship(shape);
|
||||
assertEquals(GeoArea.CONTAINS, relationship);
|
||||
|
@ -54,52 +54,52 @@ public class GeoBBoxTest {
|
|||
GeoBBox box;
|
||||
GeoPoint gp;
|
||||
// Standard normal Rect box, not crossing dateline
|
||||
box = GeoBBoxFactory.makeGeoBBox(0.0, -Math.PI * 0.25, -1.0, 1.0);
|
||||
gp = new GeoPoint(-0.1, 0.0);
|
||||
box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -1.0, 1.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 0.0);
|
||||
assertTrue(box.isWithin(gp));
|
||||
gp = new GeoPoint(0.1, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.1, 0.0);
|
||||
assertFalse(box.isWithin(gp));
|
||||
gp = new GeoPoint(-Math.PI * 0.5, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0);
|
||||
assertFalse(box.isWithin(gp));
|
||||
gp = new GeoPoint(-0.1, 1.1);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 1.1);
|
||||
assertFalse(box.isWithin(gp));
|
||||
gp = new GeoPoint(-0.1, -1.1);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -1.1);
|
||||
assertFalse(box.isWithin(gp));
|
||||
// Standard normal Rect box, crossing dateline
|
||||
box = GeoBBoxFactory.makeGeoBBox(0.0, -Math.PI * 0.25, Math.PI - 1.0, -Math.PI + 1.0);
|
||||
gp = new GeoPoint(-0.1, -Math.PI);
|
||||
box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, Math.PI - 1.0, -Math.PI + 1.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI);
|
||||
assertTrue(box.isWithin(gp));
|
||||
gp = new GeoPoint(0.1, -Math.PI);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.1, -Math.PI);
|
||||
assertFalse(box.isWithin(gp));
|
||||
gp = new GeoPoint(-Math.PI * 0.5, -Math.PI);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, -Math.PI);
|
||||
assertFalse(box.isWithin(gp));
|
||||
gp = new GeoPoint(-0.1, -Math.PI + 1.1);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI + 1.1);
|
||||
assertFalse(box.isWithin(gp));
|
||||
gp = new GeoPoint(-0.1, -Math.PI - 1.1);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI - 1.1);
|
||||
assertFalse(box.isWithin(gp));
|
||||
// Latitude zone rectangle
|
||||
box = GeoBBoxFactory.makeGeoBBox(0.0, -Math.PI * 0.25, -Math.PI, Math.PI);
|
||||
gp = new GeoPoint(-0.1, -Math.PI);
|
||||
box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -Math.PI, Math.PI);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI);
|
||||
assertTrue(box.isWithin(gp));
|
||||
gp = new GeoPoint(0.1, -Math.PI);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.1, -Math.PI);
|
||||
assertFalse(box.isWithin(gp));
|
||||
gp = new GeoPoint(-Math.PI * 0.5, -Math.PI);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, -Math.PI);
|
||||
assertFalse(box.isWithin(gp));
|
||||
gp = new GeoPoint(-0.1, -Math.PI + 1.1);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI + 1.1);
|
||||
assertTrue(box.isWithin(gp));
|
||||
gp = new GeoPoint(-0.1, -Math.PI - 1.1);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI - 1.1);
|
||||
assertTrue(box.isWithin(gp));
|
||||
// World
|
||||
box = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, Math.PI);
|
||||
gp = new GeoPoint(-0.1, -Math.PI);
|
||||
box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, Math.PI);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI);
|
||||
assertTrue(box.isWithin(gp));
|
||||
gp = new GeoPoint(0.1, -Math.PI);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.1, -Math.PI);
|
||||
assertTrue(box.isWithin(gp));
|
||||
gp = new GeoPoint(-Math.PI * 0.5, -Math.PI);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, -Math.PI);
|
||||
assertTrue(box.isWithin(gp));
|
||||
gp = new GeoPoint(-0.1, -Math.PI + 1.1);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI + 1.1);
|
||||
assertTrue(box.isWithin(gp));
|
||||
gp = new GeoPoint(-0.1, -Math.PI - 1.1);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI - 1.1);
|
||||
assertTrue(box.isWithin(gp));
|
||||
|
||||
}
|
||||
|
@ -109,23 +109,23 @@ public class GeoBBoxTest {
|
|||
GeoBBox box;
|
||||
GeoPoint gp;
|
||||
// Standard normal Rect box, not crossing dateline
|
||||
box = GeoBBoxFactory.makeGeoBBox(0.0, -Math.PI * 0.25, -1.0, 1.0);
|
||||
box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -1.0, 1.0);
|
||||
box = box.expand(0.1);
|
||||
gp = new GeoPoint(0.05, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.05, 0.0);
|
||||
assertTrue(box.isWithin(gp));
|
||||
gp = new GeoPoint(0.15, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.15, 0.0);
|
||||
assertFalse(box.isWithin(gp));
|
||||
gp = new GeoPoint(-Math.PI * 0.25 - 0.05, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.25 - 0.05, 0.0);
|
||||
assertTrue(box.isWithin(gp));
|
||||
gp = new GeoPoint(-Math.PI * 0.25 - 0.15, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.25 - 0.15, 0.0);
|
||||
assertFalse(box.isWithin(gp));
|
||||
gp = new GeoPoint(-0.1, -1.05);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -1.05);
|
||||
assertTrue(box.isWithin(gp));
|
||||
gp = new GeoPoint(-0.1, -1.15);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -1.15);
|
||||
assertFalse(box.isWithin(gp));
|
||||
gp = new GeoPoint(-0.1, 1.05);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 1.05);
|
||||
assertTrue(box.isWithin(gp));
|
||||
gp = new GeoPoint(-0.1, 1.15);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 1.15);
|
||||
assertFalse(box.isWithin(gp));
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ public class GeoBBoxTest {
|
|||
GeoBBox c;
|
||||
Bounds b;
|
||||
|
||||
c = GeoBBoxFactory.makeGeoBBox(0.0, -Math.PI * 0.25, -1.0, 1.0);
|
||||
c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -1.0, 1.0);
|
||||
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
|
@ -145,7 +145,7 @@ public class GeoBBoxTest {
|
|||
assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
|
||||
assertEquals(0.0, b.getMaxLatitude(), 0.000001);
|
||||
|
||||
c = GeoBBoxFactory.makeGeoBBox(0.0, -Math.PI * 0.25, 1.0, -1.0);
|
||||
c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, 1.0, -1.0);
|
||||
|
||||
b = c.getBounds(null);
|
||||
assertTrue(b.checkNoLongitudeBound());
|
||||
|
@ -156,7 +156,7 @@ public class GeoBBoxTest {
|
|||
assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
|
||||
assertEquals(0.0, b.getMaxLatitude(), 0.000001);
|
||||
|
||||
c = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, -1.0, 1.0);
|
||||
c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -1.0, 1.0);
|
||||
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
|
@ -165,7 +165,7 @@ public class GeoBBoxTest {
|
|||
assertEquals(-1.0, b.getLeftLongitude(), 0.000001);
|
||||
assertEquals(1.0, b.getRightLongitude(), 0.000001);
|
||||
|
||||
c = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, 1.0, -1.0);
|
||||
c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, 1.0, -1.0);
|
||||
|
||||
b = c.getBounds(null);
|
||||
assertTrue(b.checkNoLongitudeBound());
|
||||
|
@ -176,7 +176,7 @@ public class GeoBBoxTest {
|
|||
|
||||
// Check wide variants of rectangle and longitude slice
|
||||
|
||||
c = GeoBBoxFactory.makeGeoBBox(0.0, -Math.PI * 0.25, -Math.PI + 0.1, Math.PI - 0.1);
|
||||
c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -Math.PI + 0.1, Math.PI - 0.1);
|
||||
|
||||
b = c.getBounds(null);
|
||||
assertTrue(b.checkNoLongitudeBound());
|
||||
|
@ -187,7 +187,7 @@ public class GeoBBoxTest {
|
|||
assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
|
||||
assertEquals(0.0, b.getMaxLatitude(), 0.000001);
|
||||
|
||||
c = GeoBBoxFactory.makeGeoBBox(0.0, -Math.PI * 0.25, Math.PI - 0.1, -Math.PI + 0.1);
|
||||
c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, Math.PI - 0.1, -Math.PI + 0.1);
|
||||
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
|
@ -198,7 +198,7 @@ public class GeoBBoxTest {
|
|||
assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
|
||||
assertEquals(0.0, b.getMaxLatitude(), 0.000001);
|
||||
|
||||
c = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, -Math.PI + 0.1, Math.PI - 0.1);
|
||||
c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI + 0.1, Math.PI - 0.1);
|
||||
|
||||
b = c.getBounds(null);
|
||||
assertTrue(b.checkNoLongitudeBound());
|
||||
|
@ -207,7 +207,7 @@ public class GeoBBoxTest {
|
|||
//assertEquals(-Math.PI+0.1,b.getLeftLongitude(),0.000001);
|
||||
//assertEquals(Math.PI-0.1,b.getRightLongitude(),0.000001);
|
||||
|
||||
c = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, Math.PI - 0.1, -Math.PI + 0.1);
|
||||
c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, Math.PI - 0.1, -Math.PI + 0.1);
|
||||
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
|
@ -217,7 +217,7 @@ public class GeoBBoxTest {
|
|||
assertEquals(-Math.PI + 0.1, b.getRightLongitude(), 0.000001);
|
||||
|
||||
// Check latitude zone
|
||||
c = GeoBBoxFactory.makeGeoBBox(1.0, -1.0, -Math.PI, Math.PI);
|
||||
c = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 1.0, -1.0, -Math.PI, Math.PI);
|
||||
|
||||
b = c.getBounds(null);
|
||||
assertTrue(b.checkNoLongitudeBound());
|
||||
|
@ -230,8 +230,8 @@ public class GeoBBoxTest {
|
|||
GeoBBox c1;
|
||||
GeoBBox c2;
|
||||
|
||||
c1 = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, 0.0);
|
||||
c2 = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI);
|
||||
c1 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, 0.0);
|
||||
c2 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI);
|
||||
|
||||
b = new Bounds();
|
||||
b = c1.getBounds(b);
|
||||
|
@ -240,8 +240,8 @@ public class GeoBBoxTest {
|
|||
assertTrue(b.checkNoTopLatitudeBound());
|
||||
assertTrue(b.checkNoBottomLatitudeBound());
|
||||
|
||||
c1 = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, 0.0);
|
||||
c2 = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI * 0.5);
|
||||
c1 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, 0.0);
|
||||
c2 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI * 0.5);
|
||||
|
||||
b = new Bounds();
|
||||
b = c1.getBounds(b);
|
||||
|
@ -252,8 +252,8 @@ public class GeoBBoxTest {
|
|||
//assertEquals(-Math.PI,b.getLeftLongitude(),0.000001);
|
||||
//assertEquals(Math.PI*0.5,b.getRightLongitude(),0.000001);
|
||||
|
||||
c1 = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, -Math.PI * 0.5, 0.0);
|
||||
c2 = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI);
|
||||
c1 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI * 0.5, 0.0);
|
||||
c2 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI);
|
||||
|
||||
b = new Bounds();
|
||||
b = c1.getBounds(b);
|
||||
|
|
|
@ -30,16 +30,16 @@ public class GeoCircleTest {
|
|||
public void testCircleDistance() {
|
||||
GeoCircle c;
|
||||
GeoPoint gp;
|
||||
c = new GeoCircle(0.0, -0.5, 0.1);
|
||||
gp = new GeoPoint(0.0, 0.0);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, 0.0, -0.5, 0.1);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
|
||||
assertEquals(Double.MAX_VALUE, c.computeArcDistance(gp), 0.0);
|
||||
assertEquals(Double.MAX_VALUE, c.computeLinearDistance(gp), 0.0);
|
||||
assertEquals(Double.MAX_VALUE, c.computeNormalDistance(gp), 0.0);
|
||||
gp = new GeoPoint(0.0, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
|
||||
assertEquals(0.0, c.computeArcDistance(gp), 0.000001);
|
||||
assertEquals(0.0, c.computeLinearDistance(gp), 0.000001);
|
||||
assertEquals(0.0, c.computeNormalDistance(gp), 0.000001);
|
||||
gp = new GeoPoint(0.05, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.05, -0.5);
|
||||
assertEquals(0.05, c.computeArcDistance(gp), 0.000001);
|
||||
assertEquals(0.049995, c.computeLinearDistance(gp), 0.000001);
|
||||
assertEquals(0.049979, c.computeNormalDistance(gp), 0.000001);
|
||||
|
@ -49,18 +49,18 @@ public class GeoCircleTest {
|
|||
public void testCirclePointWithin() {
|
||||
GeoCircle c;
|
||||
GeoPoint gp;
|
||||
c = new GeoCircle(0.0, -0.5, 0.1);
|
||||
gp = new GeoPoint(0.0, 0.0);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, 0.0, -0.5, 0.1);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, -0.55);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, -0.45);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(Math.PI * 0.5, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.0);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, Math.PI);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
|
||||
assertFalse(c.isWithin(gp));
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ public class GeoCircleTest {
|
|||
|
||||
|
||||
// Vertical circle cases
|
||||
c = new GeoCircle(0.0, -0.5, 0.1);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, 0.0, -0.5, 0.1);
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
assertFalse(b.checkNoTopLatitudeBound());
|
||||
|
@ -80,7 +80,7 @@ public class GeoCircleTest {
|
|||
assertEquals(-0.4, b.getRightLongitude(), 0.000001);
|
||||
assertEquals(-0.1, b.getMinLatitude(), 0.000001);
|
||||
assertEquals(0.1, b.getMaxLatitude(), 0.000001);
|
||||
c = new GeoCircle(0.0, 0.5, 0.1);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, 0.0, 0.5, 0.1);
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
assertFalse(b.checkNoTopLatitudeBound());
|
||||
|
@ -89,7 +89,7 @@ public class GeoCircleTest {
|
|||
assertEquals(0.6, b.getRightLongitude(), 0.000001);
|
||||
assertEquals(-0.1, b.getMinLatitude(), 0.000001);
|
||||
assertEquals(0.1, b.getMaxLatitude(), 0.000001);
|
||||
c = new GeoCircle(0.0, 0.0, 0.1);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, 0.0, 0.0, 0.1);
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
assertFalse(b.checkNoTopLatitudeBound());
|
||||
|
@ -98,7 +98,7 @@ public class GeoCircleTest {
|
|||
assertEquals(0.1, b.getRightLongitude(), 0.000001);
|
||||
assertEquals(-0.1, b.getMinLatitude(), 0.000001);
|
||||
assertEquals(0.1, b.getMaxLatitude(), 0.000001);
|
||||
c = new GeoCircle(0.0, Math.PI, 0.1);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, 0.0, Math.PI, 0.1);
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
assertFalse(b.checkNoTopLatitudeBound());
|
||||
|
@ -108,13 +108,13 @@ public class GeoCircleTest {
|
|||
assertEquals(-0.1, b.getMinLatitude(), 0.000001);
|
||||
assertEquals(0.1, b.getMaxLatitude(), 0.000001);
|
||||
// Horizontal circle cases
|
||||
c = new GeoCircle(Math.PI * 0.5, 0.0, 0.1);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, Math.PI * 0.5, 0.0, 0.1);
|
||||
b = c.getBounds(null);
|
||||
assertTrue(b.checkNoLongitudeBound());
|
||||
assertTrue(b.checkNoTopLatitudeBound());
|
||||
assertFalse(b.checkNoBottomLatitudeBound());
|
||||
assertEquals(Math.PI * 0.5 - 0.1, b.getMinLatitude(), 0.000001);
|
||||
c = new GeoCircle(-Math.PI * 0.5, 0.0, 0.1);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0, 0.1);
|
||||
b = c.getBounds(null);
|
||||
assertTrue(b.checkNoLongitudeBound());
|
||||
assertFalse(b.checkNoTopLatitudeBound());
|
||||
|
@ -122,7 +122,7 @@ public class GeoCircleTest {
|
|||
assertEquals(-Math.PI * 0.5 + 0.1, b.getMaxLatitude(), 0.000001);
|
||||
|
||||
// Now do a somewhat tilted plane, facing different directions.
|
||||
c = new GeoCircle(0.01, 0.0, 0.1);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, 0.01, 0.0, 0.1);
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
assertFalse(b.checkNoTopLatitudeBound());
|
||||
|
@ -132,7 +132,7 @@ public class GeoCircleTest {
|
|||
assertEquals(-0.1, b.getLeftLongitude(), 0.00001);
|
||||
assertEquals(0.1, b.getRightLongitude(), 0.00001);
|
||||
|
||||
c = new GeoCircle(0.01, Math.PI, 0.1);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, 0.01, Math.PI, 0.1);
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
assertFalse(b.checkNoTopLatitudeBound());
|
||||
|
@ -142,7 +142,7 @@ public class GeoCircleTest {
|
|||
assertEquals(Math.PI - 0.1, b.getLeftLongitude(), 0.00001);
|
||||
assertEquals(-Math.PI + 0.1, b.getRightLongitude(), 0.00001);
|
||||
|
||||
c = new GeoCircle(0.01, Math.PI * 0.5, 0.1);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, 0.01, Math.PI * 0.5, 0.1);
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
assertFalse(b.checkNoTopLatitudeBound());
|
||||
|
@ -152,7 +152,7 @@ public class GeoCircleTest {
|
|||
assertEquals(Math.PI * 0.5 - 0.1, b.getLeftLongitude(), 0.00001);
|
||||
assertEquals(Math.PI * 0.5 + 0.1, b.getRightLongitude(), 0.00001);
|
||||
|
||||
c = new GeoCircle(0.01, -Math.PI * 0.5, 0.1);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, 0.01, -Math.PI * 0.5, 0.1);
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
assertFalse(b.checkNoTopLatitudeBound());
|
||||
|
@ -163,7 +163,7 @@ public class GeoCircleTest {
|
|||
assertEquals(-Math.PI * 0.5 + 0.1, b.getRightLongitude(), 0.00001);
|
||||
|
||||
// Slightly tilted, PI/4 direction.
|
||||
c = new GeoCircle(0.01, Math.PI * 0.25, 0.1);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, 0.01, Math.PI * 0.25, 0.1);
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
assertFalse(b.checkNoTopLatitudeBound());
|
||||
|
@ -173,7 +173,7 @@ public class GeoCircleTest {
|
|||
assertEquals(Math.PI * 0.25 - 0.1, b.getLeftLongitude(), 0.00001);
|
||||
assertEquals(Math.PI * 0.25 + 0.1, b.getRightLongitude(), 0.00001);
|
||||
|
||||
c = new GeoCircle(0.01, -Math.PI * 0.25, 0.1);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, 0.01, -Math.PI * 0.25, 0.1);
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
assertFalse(b.checkNoTopLatitudeBound());
|
||||
|
@ -183,7 +183,7 @@ public class GeoCircleTest {
|
|||
assertEquals(-Math.PI * 0.25 - 0.1, b.getLeftLongitude(), 0.00001);
|
||||
assertEquals(-Math.PI * 0.25 + 0.1, b.getRightLongitude(), 0.00001);
|
||||
|
||||
c = new GeoCircle(-0.01, Math.PI * 0.25, 0.1);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, -0.01, Math.PI * 0.25, 0.1);
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
assertFalse(b.checkNoTopLatitudeBound());
|
||||
|
@ -193,7 +193,7 @@ public class GeoCircleTest {
|
|||
assertEquals(Math.PI * 0.25 - 0.1, b.getLeftLongitude(), 0.00001);
|
||||
assertEquals(Math.PI * 0.25 + 0.1, b.getRightLongitude(), 0.00001);
|
||||
|
||||
c = new GeoCircle(-0.01, -Math.PI * 0.25, 0.1);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, -0.01, -Math.PI * 0.25, 0.1);
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
assertFalse(b.checkNoTopLatitudeBound());
|
||||
|
@ -204,7 +204,7 @@ public class GeoCircleTest {
|
|||
assertEquals(-Math.PI * 0.25 + 0.1, b.getRightLongitude(), 0.00001);
|
||||
|
||||
// Now do a somewhat tilted plane.
|
||||
c = new GeoCircle(0.01, -0.5, 0.1);
|
||||
c = new GeoCircle(PlanetModel.SPHERE, 0.01, -0.5, 0.1);
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
assertFalse(b.checkNoTopLatitudeBound());
|
||||
|
|
|
@ -30,37 +30,37 @@ public class GeoConvexPolygonTest {
|
|||
public void testPolygonPointWithin() {
|
||||
GeoConvexPolygon c;
|
||||
GeoPoint gp;
|
||||
c = new GeoConvexPolygon(-0.1, -0.5);
|
||||
c = new GeoConvexPolygon(PlanetModel.SPHERE, -0.1, -0.5);
|
||||
c.addPoint(0.0, -0.6, false);
|
||||
c.addPoint(0.1, -0.5, false);
|
||||
c.addPoint(0.0, -0.4, false);
|
||||
c.donePoints(false);
|
||||
// Sample some points within
|
||||
gp = new GeoPoint(0.0, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, -0.55);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, -0.45);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(-0.05, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.05, -0.5);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.05, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.05, -0.5);
|
||||
assertTrue(c.isWithin(gp));
|
||||
// Sample some nearby points outside
|
||||
gp = new GeoPoint(0.0, -0.65);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.65);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, -0.35);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.35);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(-0.15, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.15, -0.5);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.15, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.15, -0.5);
|
||||
assertFalse(c.isWithin(gp));
|
||||
// Random points outside
|
||||
gp = new GeoPoint(0.0, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(Math.PI * 0.5, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.0);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, Math.PI);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
|
||||
assertFalse(c.isWithin(gp));
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ public class GeoConvexPolygonTest {
|
|||
GeoConvexPolygon c;
|
||||
Bounds b;
|
||||
|
||||
c = new GeoConvexPolygon(-0.1, -0.5);
|
||||
c = new GeoConvexPolygon(PlanetModel.SPHERE, -0.1, -0.5);
|
||||
c.addPoint(0.0, -0.6, false);
|
||||
c.addPoint(0.1, -0.5, false);
|
||||
c.addPoint(0.0, -0.4, false);
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
package org.apache.lucene.spatial.spatial4j.geo3d;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Test basic plane functionality.
|
||||
*/
|
||||
public class GeoModelTest {
|
||||
|
||||
protected final static PlanetModel scaledModel = new PlanetModel(1.2,1.5);
|
||||
|
||||
@Test
|
||||
public void testBasicCircle() {
|
||||
// The point of this test is just to make sure nothing blows up doing normal things with a quite non-spherical model
|
||||
// Make sure that the north pole is in the circle, and south pole isn't
|
||||
final GeoPoint northPole = new GeoPoint(scaledModel, Math.PI * 0.5, 0.0);
|
||||
final GeoPoint southPole = new GeoPoint(scaledModel, -Math.PI * 0.5, 0.0);
|
||||
final GeoPoint point1 = new GeoPoint(scaledModel, Math.PI * 0.25, 0.0);
|
||||
final GeoPoint point2 = new GeoPoint(scaledModel, Math.PI * 0.125, 0.0);
|
||||
|
||||
GeoCircle circle = new GeoCircle(scaledModel, Math.PI * 0.5, 0.0, 0.01);
|
||||
assertTrue(circle.isWithin(northPole));
|
||||
assertFalse(circle.isWithin(southPole));
|
||||
assertFalse(circle.isWithin(point1));
|
||||
Bounds bounds = circle.getBounds(null);
|
||||
assertTrue(bounds.checkNoLongitudeBound());
|
||||
assertTrue(bounds.checkNoTopLatitudeBound());
|
||||
assertFalse(bounds.checkNoBottomLatitudeBound());
|
||||
assertEquals(Math.PI * 0.5 - 0.01, bounds.getMinLatitude(), 0.01);
|
||||
|
||||
circle = new GeoCircle(scaledModel, Math.PI * 0.25, 0.0, 0.01);
|
||||
assertTrue(circle.isWithin(point1));
|
||||
assertFalse(circle.isWithin(northPole));
|
||||
assertFalse(circle.isWithin(southPole));
|
||||
bounds = circle.getBounds(null);
|
||||
assertFalse(bounds.checkNoTopLatitudeBound());
|
||||
assertFalse(bounds.checkNoLongitudeBound());
|
||||
assertFalse(bounds.checkNoBottomLatitudeBound());
|
||||
assertEquals(1.20, bounds.getMaxLatitude(), 0.01);
|
||||
assertEquals(Math.PI * 0.25 - 0.01, bounds.getMinLatitude(), 0.01);
|
||||
assertEquals(-0.36, bounds.getLeftLongitude(), 0.01);
|
||||
assertEquals(0.36, bounds.getRightLongitude(), 0.01);
|
||||
|
||||
circle = new GeoCircle(scaledModel, Math.PI * 0.125, 0.0, 0.01);
|
||||
assertTrue(circle.isWithin(point2));
|
||||
assertFalse(circle.isWithin(northPole));
|
||||
assertFalse(circle.isWithin(southPole));
|
||||
bounds = circle.getBounds(null);
|
||||
assertFalse(bounds.checkNoLongitudeBound());
|
||||
assertFalse(bounds.checkNoTopLatitudeBound());
|
||||
assertFalse(bounds.checkNoBottomLatitudeBound());
|
||||
// Asymmetric, as expected
|
||||
assertEquals(Math.PI * 0.125 - 0.01, bounds.getMinLatitude(), 0.01);
|
||||
assertEquals(0.74, bounds.getMaxLatitude(), 0.01);
|
||||
assertEquals(-0.18, bounds.getLeftLongitude(), 0.01);
|
||||
assertEquals(0.18, bounds.getRightLongitude(), 0.01);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicRectangle() {
|
||||
final GeoBBox bbox = GeoBBoxFactory.makeGeoBBox(scaledModel, 1.0, 0.0, 0.0, 1.0);
|
||||
final GeoPoint insidePoint = new GeoPoint(scaledModel, 0.5, 0.5);
|
||||
assertTrue(bbox.isWithin(insidePoint));
|
||||
final GeoPoint topOutsidePoint = new GeoPoint(scaledModel, 1.01, 0.5);
|
||||
assertFalse(bbox.isWithin(topOutsidePoint));
|
||||
final GeoPoint bottomOutsidePoint = new GeoPoint(scaledModel, -0.01, 0.5);
|
||||
assertFalse(bbox.isWithin(bottomOutsidePoint));
|
||||
final GeoPoint leftOutsidePoint = new GeoPoint(scaledModel, 0.5, -0.01);
|
||||
assertFalse(bbox.isWithin(leftOutsidePoint));
|
||||
final GeoPoint rightOutsidePoint = new GeoPoint(scaledModel, 0.5, 1.01);
|
||||
assertFalse(bbox.isWithin(rightOutsidePoint));
|
||||
final Bounds bounds = bbox.getBounds(null);
|
||||
assertFalse(bounds.checkNoLongitudeBound());
|
||||
assertFalse(bounds.checkNoTopLatitudeBound());
|
||||
assertFalse(bounds.checkNoBottomLatitudeBound());
|
||||
assertEquals(1.0, bounds.getMaxLatitude(), 0.00001);
|
||||
assertEquals(0.0, bounds.getMinLatitude(), 0.00001);
|
||||
assertEquals(1.0, bounds.getRightLongitude(), 0.00001);
|
||||
assertEquals(0.0, bounds.getLeftLongitude(), 0.00001);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -30,47 +30,47 @@ public class GeoPathTest {
|
|||
// Start with a really simple case
|
||||
GeoPath p;
|
||||
GeoPoint gp;
|
||||
p = new GeoPath(0.1);
|
||||
p = new GeoPath(PlanetModel.SPHERE, 0.1);
|
||||
p.addPoint(0.0, 0.0);
|
||||
p.addPoint(0.0, 0.1);
|
||||
p.addPoint(0.0, 0.2);
|
||||
p.done();
|
||||
gp = new GeoPoint(Math.PI * 0.5, 0.15);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.15);
|
||||
assertEquals(Double.MAX_VALUE, p.computeArcDistance(gp), 0.0);
|
||||
gp = new GeoPoint(0.05, 0.15);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.05, 0.15);
|
||||
assertEquals(0.15 + 0.05, p.computeArcDistance(gp), 0.000001);
|
||||
gp = new GeoPoint(0.0, 0.12);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.12);
|
||||
assertEquals(0.12 + 0.0, p.computeArcDistance(gp), 0.000001);
|
||||
gp = new GeoPoint(-0.15, 0.05);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.15, 0.05);
|
||||
assertEquals(Double.MAX_VALUE, p.computeArcDistance(gp), 0.000001);
|
||||
gp = new GeoPoint(0.0, 0.25);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.25);
|
||||
assertEquals(0.20 + 0.05, p.computeArcDistance(gp), 0.000001);
|
||||
gp = new GeoPoint(0.0, -0.05);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.05);
|
||||
assertEquals(0.0 + 0.05, p.computeArcDistance(gp), 0.000001);
|
||||
|
||||
// Compute path distances now
|
||||
p = new GeoPath(0.1);
|
||||
p = new GeoPath(PlanetModel.SPHERE, 0.1);
|
||||
p.addPoint(0.0, 0.0);
|
||||
p.addPoint(0.0, 0.1);
|
||||
p.addPoint(0.0, 0.2);
|
||||
p.done();
|
||||
gp = new GeoPoint(0.05, 0.15);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.05, 0.15);
|
||||
assertEquals(0.15 + 0.05, p.computeArcDistance(gp), 0.000001);
|
||||
gp = new GeoPoint(0.0, 0.12);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.12);
|
||||
assertEquals(0.12, p.computeArcDistance(gp), 0.000001);
|
||||
|
||||
// Now try a vertical path, and make sure distances are as expected
|
||||
p = new GeoPath(0.1);
|
||||
p = new GeoPath(PlanetModel.SPHERE, 0.1);
|
||||
p.addPoint(-Math.PI * 0.25, -0.5);
|
||||
p.addPoint(Math.PI * 0.25, -0.5);
|
||||
p.done();
|
||||
gp = new GeoPoint(0.0, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
|
||||
assertEquals(Double.MAX_VALUE, p.computeArcDistance(gp), 0.0);
|
||||
gp = new GeoPoint(-0.1, -1.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -1.0);
|
||||
assertEquals(Double.MAX_VALUE, p.computeArcDistance(gp), 0.0);
|
||||
gp = new GeoPoint(Math.PI * 0.25 + 0.05, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.25 + 0.05, -0.5);
|
||||
assertEquals(Math.PI * 0.5 + 0.05, p.computeArcDistance(gp), 0.000001);
|
||||
gp = new GeoPoint(-Math.PI * 0.25 - 0.05, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.25 - 0.05, -0.5);
|
||||
assertEquals(0.0 + 0.05, p.computeArcDistance(gp), 0.000001);
|
||||
}
|
||||
|
||||
|
@ -79,47 +79,48 @@ public class GeoPathTest {
|
|||
// Tests whether we can properly detect whether a point is within a path or not
|
||||
GeoPath p;
|
||||
GeoPoint gp;
|
||||
p = new GeoPath(0.1);
|
||||
p = new GeoPath(PlanetModel.SPHERE, 0.1);
|
||||
// Build a diagonal path crossing the equator
|
||||
p.addPoint(-0.2, -0.2);
|
||||
p.addPoint(0.2, 0.2);
|
||||
p.done();
|
||||
// Test points on the path
|
||||
gp = new GeoPoint(-0.2, -0.2);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.2, -0.2);
|
||||
assertTrue(p.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
|
||||
assertTrue(p.isWithin(gp));
|
||||
gp = new GeoPoint(0.1, 0.1);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.1, 0.1);
|
||||
assertTrue(p.isWithin(gp));
|
||||
// Test points off the path
|
||||
gp = new GeoPoint(-0.2, 0.2);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.2, 0.2);
|
||||
assertFalse(p.isWithin(gp));
|
||||
gp = new GeoPoint(-Math.PI * 0.5, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0);
|
||||
assertFalse(p.isWithin(gp));
|
||||
gp = new GeoPoint(0.2, -0.2);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.2, -0.2);
|
||||
assertFalse(p.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, Math.PI);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
|
||||
assertFalse(p.isWithin(gp));
|
||||
// Repeat the test, but across the terminator
|
||||
p = new GeoPath(0.1);
|
||||
p = new GeoPath(PlanetModel.SPHERE, 0.1);
|
||||
// Build a diagonal path crossing the equator
|
||||
p.addPoint(-0.2, Math.PI - 0.2);
|
||||
p.addPoint(0.2, -Math.PI + 0.2);
|
||||
p.done();
|
||||
// Test points on the path
|
||||
gp = new GeoPoint(-0.2, Math.PI - 0.2);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.2, Math.PI - 0.2);
|
||||
assertTrue(p.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, Math.PI);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
|
||||
assertTrue(p.isWithin(gp));
|
||||
gp = new GeoPoint(0.1, -Math.PI + 0.1);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.1, -Math.PI + 0.1);
|
||||
assertTrue(p.isWithin(gp));
|
||||
// Test points off the path
|
||||
gp = new GeoPoint(-0.2, -Math.PI + 0.2);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.2, -Math.PI + 0.2);
|
||||
assertFalse(p.isWithin(gp));
|
||||
gp = new GeoPoint(-Math.PI * 0.5, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -Math.PI * 0.5, 0.0);
|
||||
assertFalse(p.isWithin(gp));
|
||||
gp = new GeoPoint(0.2, Math.PI - 0.2);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.2, Math.PI - 0.2);
|
||||
assertFalse(p.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
|
||||
assertFalse(p.isWithin(gp));
|
||||
|
||||
}
|
||||
|
@ -131,31 +132,31 @@ public class GeoPathTest {
|
|||
|
||||
// Start by testing the basic kinds of relationship, increasing in order of difficulty.
|
||||
|
||||
p = new GeoPath(0.1);
|
||||
p = new GeoPath(PlanetModel.SPHERE, 0.1);
|
||||
p.addPoint(-0.3, -0.3);
|
||||
p.addPoint(0.3, 0.3);
|
||||
p.done();
|
||||
// Easiest: The path is wholly contains the georect
|
||||
rect = new GeoRectangle(0.05, -0.05, -0.05, 0.05);
|
||||
rect = new GeoRectangle(PlanetModel.SPHERE, 0.05, -0.05, -0.05, 0.05);
|
||||
assertEquals(GeoArea.CONTAINS, rect.getRelationship(p));
|
||||
// Next easiest: Some endpoints of the rectangle are inside, and some are outside.
|
||||
rect = new GeoRectangle(0.05, -0.05, -0.05, 0.5);
|
||||
rect = new GeoRectangle(PlanetModel.SPHERE, 0.05, -0.05, -0.05, 0.5);
|
||||
assertEquals(GeoArea.OVERLAPS, rect.getRelationship(p));
|
||||
// Now, all points are outside, but the figures intersect
|
||||
rect = new GeoRectangle(0.05, -0.05, -0.5, 0.5);
|
||||
rect = new GeoRectangle(PlanetModel.SPHERE, 0.05, -0.05, -0.5, 0.5);
|
||||
assertEquals(GeoArea.OVERLAPS, rect.getRelationship(p));
|
||||
// Finally, all points are outside, and the figures *do not* intersect
|
||||
rect = new GeoRectangle(0.5, -0.5, -0.5, 0.5);
|
||||
rect = new GeoRectangle(PlanetModel.SPHERE, 0.5, -0.5, -0.5, 0.5);
|
||||
assertEquals(GeoArea.WITHIN, rect.getRelationship(p));
|
||||
// Check that segment edge overlap detection works
|
||||
rect = new GeoRectangle(0.1, 0.0, -0.1, 0.0);
|
||||
rect = new GeoRectangle(PlanetModel.SPHERE, 0.1, 0.0, -0.1, 0.0);
|
||||
assertEquals(GeoArea.OVERLAPS, rect.getRelationship(p));
|
||||
rect = new GeoRectangle(0.2, 0.1, -0.2, -0.1);
|
||||
rect = new GeoRectangle(PlanetModel.SPHERE, 0.2, 0.1, -0.2, -0.1);
|
||||
assertEquals(GeoArea.DISJOINT, rect.getRelationship(p));
|
||||
// Check if overlap at endpoints behaves as expected next
|
||||
rect = new GeoRectangle(0.5, -0.5, -0.5, -0.35);
|
||||
rect = new GeoRectangle(PlanetModel.SPHERE, 0.5, -0.5, -0.5, -0.35);
|
||||
assertEquals(GeoArea.OVERLAPS, rect.getRelationship(p));
|
||||
rect = new GeoRectangle(0.5, -0.5, -0.5, -0.45);
|
||||
rect = new GeoRectangle(PlanetModel.SPHERE, 0.5, -0.5, -0.5, -0.45);
|
||||
assertEquals(GeoArea.DISJOINT, rect.getRelationship(p));
|
||||
|
||||
}
|
||||
|
@ -165,7 +166,7 @@ public class GeoPathTest {
|
|||
GeoPath c;
|
||||
Bounds b;
|
||||
|
||||
c = new GeoPath(0.1);
|
||||
c = new GeoPath(PlanetModel.SPHERE, 0.1);
|
||||
c.addPoint(-0.3, -0.3);
|
||||
c.addPoint(0.3, 0.3);
|
||||
c.done();
|
||||
|
|
|
@ -36,49 +36,49 @@ public class GeoPolygonTest {
|
|||
List<GeoPoint> points;
|
||||
|
||||
points = new ArrayList<GeoPoint>();
|
||||
points.add(new GeoPoint(-0.1, -0.5));
|
||||
points.add(new GeoPoint(0.0, -0.6));
|
||||
points.add(new GeoPoint(0.1, -0.5));
|
||||
points.add(new GeoPoint(0.0, -0.4));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.5));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.6));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.5));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.4));
|
||||
|
||||
c = GeoPolygonFactory.makeGeoPolygon(points, 0);
|
||||
c = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points, 0);
|
||||
// Sample some points within
|
||||
gp = new GeoPoint(0.0, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, -0.55);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, -0.45);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(-0.05, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.05, -0.5);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.05, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.05, -0.5);
|
||||
assertTrue(c.isWithin(gp));
|
||||
// Sample some nearby points outside
|
||||
gp = new GeoPoint(0.0, -0.65);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.65);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, -0.35);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.35);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(-0.15, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.15, -0.5);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.15, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.15, -0.5);
|
||||
assertFalse(c.isWithin(gp));
|
||||
// Random points outside
|
||||
gp = new GeoPoint(0.0, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(Math.PI * 0.5, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.0);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, Math.PI);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
|
||||
assertFalse(c.isWithin(gp));
|
||||
|
||||
points = new ArrayList<GeoPoint>();
|
||||
points.add(new GeoPoint(-0.1, -0.5));
|
||||
points.add(new GeoPoint(-0.01, -0.6));
|
||||
points.add(new GeoPoint(-0.1, -0.7));
|
||||
points.add(new GeoPoint(0.0, -0.8));
|
||||
points.add(new GeoPoint(0.1, -0.7));
|
||||
points.add(new GeoPoint(0.01, -0.6));
|
||||
points.add(new GeoPoint(0.1, -0.5));
|
||||
points.add(new GeoPoint(0.0, -0.4));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.5));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, -0.01, -0.6));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.7));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.8));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.7));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, 0.01, -0.6));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.5));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.4));
|
||||
|
||||
/*
|
||||
System.out.println("Points: ");
|
||||
|
@ -87,33 +87,33 @@ public class GeoPolygonTest {
|
|||
}
|
||||
*/
|
||||
|
||||
c = GeoPolygonFactory.makeGeoPolygon(points, 0);
|
||||
c = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points, 0);
|
||||
// Sample some points within
|
||||
gp = new GeoPoint(0.0, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, -0.55);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, -0.45);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(-0.05, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.05, -0.5);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.05, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.05, -0.5);
|
||||
assertTrue(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, -0.7);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.7);
|
||||
assertTrue(c.isWithin(gp));
|
||||
// Sample some nearby points outside
|
||||
gp = new GeoPoint(0.0, -0.35);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.35);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(-0.15, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, -0.15, -0.5);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.15, -0.5);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.15, -0.5);
|
||||
assertFalse(c.isWithin(gp));
|
||||
// Random points outside
|
||||
gp = new GeoPoint(0.0, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(Math.PI * 0.5, 0.0);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, Math.PI * 0.5, 0.0);
|
||||
assertFalse(c.isWithin(gp));
|
||||
gp = new GeoPoint(0.0, Math.PI);
|
||||
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
|
||||
assertFalse(c.isWithin(gp));
|
||||
|
||||
}
|
||||
|
@ -125,12 +125,12 @@ public class GeoPolygonTest {
|
|||
List<GeoPoint> points;
|
||||
|
||||
points = new ArrayList<GeoPoint>();
|
||||
points.add(new GeoPoint(-0.1, -0.5));
|
||||
points.add(new GeoPoint(0.0, -0.6));
|
||||
points.add(new GeoPoint(0.1, -0.5));
|
||||
points.add(new GeoPoint(0.0, -0.4));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.5));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.6));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.5));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.4));
|
||||
|
||||
c = GeoPolygonFactory.makeGeoPolygon(points, 0);
|
||||
c = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points, 0);
|
||||
|
||||
b = c.getBounds(null);
|
||||
assertFalse(b.checkNoLongitudeBound());
|
||||
|
|
|
@ -30,7 +30,7 @@ public class PlaneTest {
|
|||
|
||||
@Test
|
||||
public void testIdenticalPlanes() {
|
||||
final GeoPoint p = new GeoPoint(0.123, -0.456);
|
||||
final GeoPoint p = new GeoPoint(PlanetModel.SPHERE, 0.123, -0.456);
|
||||
final Plane plane1 = new Plane(p, 0.0);
|
||||
final Plane plane2 = new Plane(p, 0.0);
|
||||
assertTrue(plane1.isNumericallyIdentical(plane2));
|
||||
|
|
Loading…
Reference in New Issue