mirror of https://github.com/apache/lucene.git
LUCENE-6487: Geo3D with WGS84 option (Merged from lucene6487 + CHANGES.txt)
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1683100 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
commit
77de0ed1cf
|
@ -47,6 +47,9 @@ New Features
|
||||||
FuzzyCompletionQuery and ContextQuery.
|
FuzzyCompletionQuery and ContextQuery.
|
||||||
(Areek Zillur via Mike McCandless)
|
(Areek Zillur via Mike McCandless)
|
||||||
|
|
||||||
|
* LUCENE-6487: Spatial Geo3D API now has a WGS84 ellipsoid world model option.
|
||||||
|
(Karl Wright via David Smiley)
|
||||||
|
|
||||||
Bug fixes
|
Bug fixes
|
||||||
|
|
||||||
* LUCENE-6500: ParallelCompositeReader did not always call
|
* LUCENE-6500: ParallelCompositeReader did not always call
|
||||||
|
|
|
@ -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.GeoAreaFactory;
|
||||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoPoint;
|
import org.apache.lucene.spatial.spatial4j.geo3d.GeoPoint;
|
||||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoShape;
|
import org.apache.lucene.spatial.spatial4j.geo3d.GeoShape;
|
||||||
|
import org.apache.lucene.spatial.spatial4j.geo3d.PlanetModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A 3D planar geometry based Spatial4j Shape implementation.
|
* A 3D planar geometry based Spatial4j Shape implementation.
|
||||||
|
@ -38,17 +39,23 @@ public class Geo3dShape implements Shape {
|
||||||
|
|
||||||
public final SpatialContext ctx;
|
public final SpatialContext ctx;
|
||||||
public final GeoShape shape;
|
public final GeoShape shape;
|
||||||
|
public final PlanetModel planetModel;
|
||||||
|
|
||||||
private Rectangle boundingBox = null;
|
private Rectangle boundingBox = null;
|
||||||
|
|
||||||
public final static double RADIANS_PER_DEGREE = Math.PI / 180.0;
|
public final static double RADIANS_PER_DEGREE = Math.PI / 180.0;
|
||||||
public final static double DEGREES_PER_RADIAN = 1.0 / RADIANS_PER_DEGREE;
|
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()) {
|
if (!ctx.isGeo()) {
|
||||||
throw new IllegalArgumentException("SpatialContext.isGeo() must be true");
|
throw new IllegalArgumentException("SpatialContext.isGeo() must be true");
|
||||||
}
|
}
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
|
this.planetModel = planetModel;
|
||||||
this.shape = shape;
|
this.shape = shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +71,8 @@ public class Geo3dShape implements Shape {
|
||||||
|
|
||||||
protected SpatialRelation relate(Rectangle r) {
|
protected SpatialRelation relate(Rectangle r) {
|
||||||
// Construct the right kind of GeoArea first
|
// 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.getMinY() * RADIANS_PER_DEGREE,
|
||||||
r.getMinX() * RADIANS_PER_DEGREE,
|
r.getMinX() * RADIANS_PER_DEGREE,
|
||||||
r.getMaxX() * RADIANS_PER_DEGREE);
|
r.getMaxX() * RADIANS_PER_DEGREE);
|
||||||
|
@ -83,7 +91,7 @@ public class Geo3dShape implements Shape {
|
||||||
|
|
||||||
protected SpatialRelation relate(Point p) {
|
protected SpatialRelation relate(Point p) {
|
||||||
// Create a GeoPoint
|
// 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)) {
|
if (shape.isWithin(point)) {
|
||||||
// Point within shape
|
// Point within shape
|
||||||
return SpatialRelation.CONTAINS;
|
return SpatialRelation.CONTAINS;
|
||||||
|
@ -91,7 +99,9 @@ public class Geo3dShape implements Shape {
|
||||||
return SpatialRelation.DISJOINT;
|
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
|
@Override
|
||||||
public Rectangle getBoundingBox() {
|
public Rectangle getBoundingBox() {
|
||||||
|
@ -150,7 +160,7 @@ public class Geo3dShape implements Shape {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Geo3dShape{" + shape + '}';
|
return "Geo3dShape{planetmodel=" + planetModel+", shape="+shape + '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -158,11 +168,11 @@ public class Geo3dShape implements Shape {
|
||||||
if (!(other instanceof Geo3dShape))
|
if (!(other instanceof Geo3dShape))
|
||||||
return false;
|
return false;
|
||||||
Geo3dShape tr = (Geo3dShape)other;
|
Geo3dShape tr = (Geo3dShape)other;
|
||||||
return tr.shape.equals(shape);
|
return tr.planetModel.equals(planetModel) && tr.shape.equals(shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
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);
|
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) {
|
if (!noLongitudeBound) {
|
||||||
// Get a longitude value
|
// Get a longitude value
|
||||||
double longitude = Math.atan2(y, x);
|
double longitude = Math.atan2(y, x);
|
||||||
|
@ -267,7 +267,7 @@ public class Bounds {
|
||||||
}
|
}
|
||||||
if (!noTopLatitudeBound || !noBottomLatitudeBound) {
|
if (!noTopLatitudeBound || !noBottomLatitudeBound) {
|
||||||
// Compute a latitude value
|
// Compute a latitude value
|
||||||
double latitude = Math.asin(z);
|
double latitude = Math.asin(z/Math.sqrt(z * z + x * x + y * y));
|
||||||
addLatitudeBound(latitude);
|
addLatitudeBound(latitude);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -35,8 +35,8 @@ public class GeoAreaFactory {
|
||||||
* @param rightLon is the right longitude
|
* @param rightLon is the right longitude
|
||||||
* @return a GeoArea corresponding to what was specified.
|
* @return a GeoArea corresponding to what was specified.
|
||||||
*/
|
*/
|
||||||
public static GeoArea makeGeoArea(double topLat, double bottomLat, double leftLon, double rightLon) {
|
public static GeoArea makeGeoArea(final PlanetModel planetModel, final double topLat, final double bottomLat, final double leftLon, final double rightLon) {
|
||||||
return GeoBBoxFactory.makeGeoBBox(topLat, bottomLat, leftLon, 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.
|
* Create a geobbox of the right kind given the specified bounds.
|
||||||
*
|
*
|
||||||
|
* @param planetModel is the planet model
|
||||||
* @param topLat is the top latitude
|
* @param topLat is the top latitude
|
||||||
* @param bottomLat is the bottom latitude
|
* @param bottomLat is the bottom latitude
|
||||||
* @param leftLon is the left longitude
|
* @param leftLon is the left longitude
|
||||||
* @param rightLon is the right longitude
|
* @param rightLon is the right longitude
|
||||||
* @return a GeoBBox corresponding to what was specified.
|
* @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);
|
//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)
|
if (topLat > Math.PI * 0.5)
|
||||||
topLat = Math.PI * 0.5;
|
topLat = Math.PI * 0.5;
|
||||||
|
@ -47,17 +48,17 @@ public class GeoBBoxFactory {
|
||||||
rightLon = Math.PI;
|
rightLon = Math.PI;
|
||||||
if (Math.abs(leftLon + Math.PI) < Vector.MINIMUM_RESOLUTION && Math.abs(rightLon - Math.PI) < Vector.MINIMUM_RESOLUTION) {
|
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)
|
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 - 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)
|
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);
|
||||||
return new GeoDegenerateLatitudeZone(topLat);
|
return new GeoDegenerateLatitudeZone(planetModel, topLat);
|
||||||
}
|
}
|
||||||
if (Math.abs(topLat - Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION)
|
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)
|
else if (Math.abs(bottomLat + Math.PI * 0.5) < Vector.MINIMUM_RESOLUTION)
|
||||||
return new GeoSouthLatitudeZone(topLat);
|
return new GeoSouthLatitudeZone(planetModel, topLat);
|
||||||
return new GeoLatitudeZone(topLat, bottomLat);
|
return new GeoLatitudeZone(planetModel, topLat, bottomLat);
|
||||||
}
|
}
|
||||||
//System.err.println(" not latitude zone");
|
//System.err.println(" not latitude zone");
|
||||||
double extent = rightLon - leftLon;
|
double extent = rightLon - leftLon;
|
||||||
|
@ -65,47 +66,47 @@ public class GeoBBoxFactory {
|
||||||
extent += Math.PI * 2.0;
|
extent += Math.PI * 2.0;
|
||||||
if (topLat == Math.PI * 0.5 && bottomLat == -Math.PI * 0.5) {
|
if (topLat == Math.PI * 0.5 && bottomLat == -Math.PI * 0.5) {
|
||||||
if (Math.abs(leftLon - rightLon) < Vector.MINIMUM_RESOLUTION)
|
if (Math.abs(leftLon - rightLon) < Vector.MINIMUM_RESOLUTION)
|
||||||
return new GeoDegenerateLongitudeSlice(leftLon);
|
return new GeoDegenerateLongitudeSlice(planetModel, leftLon);
|
||||||
|
|
||||||
if (extent >= Math.PI)
|
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");
|
//System.err.println(" not longitude slice");
|
||||||
if (Math.abs(leftLon - rightLon) < Vector.MINIMUM_RESOLUTION) {
|
if (Math.abs(leftLon - rightLon) < Vector.MINIMUM_RESOLUTION) {
|
||||||
if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION)
|
if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION)
|
||||||
return new GeoDegeneratePoint(topLat, leftLon);
|
return new GeoDegeneratePoint(planetModel, topLat, leftLon);
|
||||||
return new GeoDegenerateVerticalLine(topLat, bottomLat, leftLon);
|
return new GeoDegenerateVerticalLine(planetModel, topLat, bottomLat, leftLon);
|
||||||
}
|
}
|
||||||
//System.err.println(" not vertical line");
|
//System.err.println(" not vertical line");
|
||||||
if (extent >= Math.PI) {
|
if (extent >= Math.PI) {
|
||||||
if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION) {
|
if (Math.abs(topLat - bottomLat) < Vector.MINIMUM_RESOLUTION) {
|
||||||
//System.err.println(" wide degenerate line");
|
//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) {
|
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) {
|
} 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");
|
//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 - 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) {
|
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");
|
//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) {
|
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) {
|
} 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");
|
//System.err.println(" rectangle");
|
||||||
return new GeoRectangle(topLat, bottomLat, leftLon, rightLon);
|
return new GeoRectangle(planetModel, topLat, bottomLat, leftLon, rightLon);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,11 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
||||||
*
|
*
|
||||||
* @lucene.internal
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public abstract class GeoBBoxBase implements GeoBBox {
|
public abstract class GeoBaseBBox extends GeoBaseShape implements GeoBBox {
|
||||||
|
|
||||||
protected final static GeoPoint NORTH_POLE = new GeoPoint(0.0, 0.0, 1.0);
|
public GeoBaseBBox(final PlanetModel planetModel) {
|
||||||
protected final static GeoPoint SOUTH_POLE = new GeoPoint(0.0, 0.0, -1.0);
|
super(planetModel);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract boolean isWithin(final Vector point);
|
public abstract boolean isWithin(final Vector point);
|
||||||
|
@ -45,6 +46,9 @@ public abstract class GeoBBoxBase implements GeoBBox {
|
||||||
} else {
|
} else {
|
||||||
foundOutside = true;
|
foundOutside = true;
|
||||||
}
|
}
|
||||||
|
if (foundInside && foundOutside) {
|
||||||
|
return SOME_INSIDE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!foundInside && !foundOutside)
|
if (!foundInside && !foundOutside)
|
||||||
return NONE_INSIDE;
|
return NONE_INSIDE;
|
||||||
|
@ -54,5 +58,15 @@ public abstract class GeoBBoxBase implements GeoBBox {
|
||||||
return NONE_INSIDE;
|
return NONE_INSIDE;
|
||||||
return SOME_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
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public abstract class GeoBaseExtendedShape implements GeoShape {
|
public abstract class GeoBaseExtendedShape extends GeoBaseShape 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 GeoBaseExtendedShape() {
|
public GeoBaseExtendedShape(final PlanetModel planetModel) {
|
||||||
|
super(planetModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -83,12 +82,22 @@ public abstract class GeoBaseExtendedShape implements GeoShape {
|
||||||
public Bounds getBounds(Bounds bounds) {
|
public Bounds getBounds(Bounds bounds) {
|
||||||
if (bounds == null)
|
if (bounds == null)
|
||||||
bounds = new Bounds();
|
bounds = new Bounds();
|
||||||
if (isWithin(NORTH_POLE)) {
|
if (isWithin(planetModel.NORTH_POLE)) {
|
||||||
bounds.noTopLatitudeBound().noLongitudeBound();
|
bounds.noTopLatitudeBound().noLongitudeBound();
|
||||||
}
|
}
|
||||||
if (isWithin(SOUTH_POLE)) {
|
if (isWithin(planetModel.SOUTH_POLE)) {
|
||||||
bounds.noBottomLatitudeBound().noLongitudeBound();
|
bounds.noBottomLatitudeBound().noLongitudeBound();
|
||||||
}
|
}
|
||||||
return bounds;
|
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 class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape, GeoSizeable {
|
||||||
public final GeoPoint center;
|
public final GeoPoint center;
|
||||||
public final double cutoffAngle;
|
public final double cutoffAngle;
|
||||||
public final double cutoffNormalDistance;
|
|
||||||
public final double cutoffLinearDistance;
|
|
||||||
public final SidedPlane circlePlane;
|
public final SidedPlane circlePlane;
|
||||||
public final GeoPoint[] edgePoints;
|
public final GeoPoint[] edgePoints;
|
||||||
public static final GeoPoint[] circlePoints = new GeoPoint[0];
|
public static final GeoPoint[] circlePoints = new GeoPoint[0];
|
||||||
|
|
||||||
public GeoCircle(final double lat, final double lon, final double cutoffAngle) {
|
public GeoCircle(final PlanetModel planetModel, final double lat, final double lon, final double cutoffAngle) {
|
||||||
super();
|
super(planetModel);
|
||||||
if (lat < -Math.PI * 0.5 || lat > Math.PI * 0.5)
|
if (lat < -Math.PI * 0.5 || lat > Math.PI * 0.5)
|
||||||
throw new IllegalArgumentException("Latitude out of bounds");
|
throw new IllegalArgumentException("Latitude out of bounds");
|
||||||
if (lon < -Math.PI || lon > Math.PI)
|
if (lon < -Math.PI || lon > Math.PI)
|
||||||
throw new IllegalArgumentException("Longitude out of bounds");
|
throw new IllegalArgumentException("Longitude out of bounds");
|
||||||
if (cutoffAngle <= 0.0 || cutoffAngle > Math.PI)
|
if (cutoffAngle <= 0.0 || cutoffAngle > Math.PI)
|
||||||
throw new IllegalArgumentException("Cutoff angle out of bounds");
|
throw new IllegalArgumentException("Cutoff angle out of bounds");
|
||||||
final double sinAngle = Math.sin(cutoffAngle);
|
|
||||||
final double cosAngle = Math.cos(cutoffAngle);
|
final double cosAngle = Math.cos(cutoffAngle);
|
||||||
this.center = new GeoPoint(lat, lon);
|
this.center = new GeoPoint(planetModel, lat, lon);
|
||||||
this.cutoffNormalDistance = sinAngle;
|
final double magnitude = center.magnitude();
|
||||||
// Need the chord distance. This is just the chord distance: sqrt((1 - cos(angle))^2 + (sin(angle))^2).
|
// In an ellipsoidal world, cutoff distances make no sense, unfortunately. Only membership
|
||||||
final double xDiff = 1.0 - cosAngle;
|
// can be used to make in/out determination.
|
||||||
this.cutoffLinearDistance = Math.sqrt(xDiff * xDiff + sinAngle * sinAngle);
|
|
||||||
this.cutoffAngle = cutoffAngle;
|
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.
|
// Compute a point on the circle boundary.
|
||||||
if (cutoffAngle == Math.PI)
|
if (cutoffAngle == Math.PI)
|
||||||
this.edgePoints = new GeoPoint[0];
|
this.edgePoints = new GeoPoint[0];
|
||||||
else {
|
else {
|
||||||
// Move from center only in latitude. Then, if we go past the north pole, adjust the longitude also.
|
// We already have circle plane, which is the definitive determination of the edge of the "circle".
|
||||||
double newLat = lat + cutoffAngle;
|
// Next, compute vertical plane going through origin and the center point (C = 0, D = 0).
|
||||||
double newLon = lon;
|
Plane verticalPlane = Plane.constructNormalizedVerticalPlane(this.center.x, this.center.y);
|
||||||
if (newLat > Math.PI * 0.5) {
|
if (verticalPlane == null) {
|
||||||
newLat = Math.PI - newLat;
|
verticalPlane = new Plane(1.0,0.0);
|
||||||
newLon += Math.PI;
|
|
||||||
}
|
}
|
||||||
while (newLon > Math.PI) {
|
// Finally, use Plane.findIntersections() to find the intersection points.
|
||||||
newLon -= Math.PI * 2.0;
|
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)
|
//if (Math.abs(circlePlane.evaluate(edgePoint)) > 1e-10)
|
||||||
// throw new RuntimeException("Computed an edge point that does not satisfy circlePlane equation! "+circlePlane.evaluate(edgePoint));
|
// throw new RuntimeException("Computed an edge point that does not satisfy circlePlane equation! "+circlePlane.evaluate(edgePoint));
|
||||||
this.edgePoints = new GeoPoint[]{edgePoint};
|
this.edgePoints = new GeoPoint[]{edgePoint};
|
||||||
|
@ -92,10 +89,9 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public double computeNormalDistance(final GeoPoint point) {
|
public double computeNormalDistance(final GeoPoint point) {
|
||||||
double normalDistance = this.center.normalDistance(point);
|
if (!isWithin(point))
|
||||||
if (normalDistance > cutoffNormalDistance)
|
|
||||||
return Double.MAX_VALUE;
|
return Double.MAX_VALUE;
|
||||||
return normalDistance;
|
return this.center.normalDistance(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,10 +101,9 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public double computeNormalDistance(final double x, final double y, final double z) {
|
public double computeNormalDistance(final double x, final double y, final double z) {
|
||||||
double normalDistance = this.center.normalDistance(x, y, z);
|
if (!isWithin(x,y,z))
|
||||||
if (normalDistance > cutoffNormalDistance)
|
|
||||||
return Double.MAX_VALUE;
|
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
|
@Override
|
||||||
public double computeSquaredNormalDistance(final GeoPoint point) {
|
public double computeSquaredNormalDistance(final GeoPoint point) {
|
||||||
double normalDistanceSquared = this.center.normalDistanceSquared(point);
|
if (!isWithin(point))
|
||||||
if (normalDistanceSquared > cutoffNormalDistance * cutoffNormalDistance)
|
|
||||||
return Double.MAX_VALUE;
|
return Double.MAX_VALUE;
|
||||||
return normalDistanceSquared;
|
return this.center.normalDistanceSquared(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -131,10 +125,9 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public double computeSquaredNormalDistance(final double x, final double y, final double z) {
|
public double computeSquaredNormalDistance(final double x, final double y, final double z) {
|
||||||
double normalDistanceSquared = this.center.normalDistanceSquared(x, y, z);
|
if (!isWithin(x,y,z))
|
||||||
if (normalDistanceSquared > cutoffNormalDistance * cutoffNormalDistance)
|
|
||||||
return Double.MAX_VALUE;
|
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
|
@Override
|
||||||
public double computeLinearDistance(final GeoPoint point) {
|
public double computeLinearDistance(final GeoPoint point) {
|
||||||
double linearDistance = this.center.linearDistance(point);
|
if (!isWithin(point))
|
||||||
if (linearDistance > cutoffLinearDistance)
|
|
||||||
return Double.MAX_VALUE;
|
return Double.MAX_VALUE;
|
||||||
return linearDistance;
|
return this.center.linearDistance(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -155,10 +147,9 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public double computeLinearDistance(final double x, final double y, final double z) {
|
public double computeLinearDistance(final double x, final double y, final double z) {
|
||||||
double linearDistance = this.center.linearDistance(x, y, z);
|
if (!isWithin(x,y,z))
|
||||||
if (linearDistance > cutoffLinearDistance)
|
|
||||||
return Double.MAX_VALUE;
|
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
|
@Override
|
||||||
public double computeSquaredLinearDistance(final GeoPoint point) {
|
public double computeSquaredLinearDistance(final GeoPoint point) {
|
||||||
double linearDistanceSquared = this.center.linearDistanceSquared(point);
|
if (!isWithin(point))
|
||||||
if (linearDistanceSquared > cutoffLinearDistance * cutoffLinearDistance)
|
|
||||||
return Double.MAX_VALUE;
|
return Double.MAX_VALUE;
|
||||||
return linearDistanceSquared;
|
return this.center.linearDistanceSquared(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -177,10 +167,9 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public double computeSquaredLinearDistance(final double x, final double y, final double z) {
|
public double computeSquaredLinearDistance(final double x, final double y, final double z) {
|
||||||
double linearDistanceSquared = this.center.linearDistanceSquared(x, y, z);
|
if (!isWithin(x,y,z))
|
||||||
if (linearDistanceSquared > cutoffLinearDistance * cutoffLinearDistance)
|
|
||||||
return Double.MAX_VALUE;
|
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
|
@Override
|
||||||
public double computeArcDistance(final GeoPoint point) {
|
public double computeArcDistance(final GeoPoint point) {
|
||||||
double dist = this.center.arcDistance(point);
|
if (!isWithin(point))
|
||||||
if (dist > cutoffAngle)
|
|
||||||
return Double.MAX_VALUE;
|
return Double.MAX_VALUE;
|
||||||
return dist;
|
return this.center.arcDistance(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -214,7 +202,7 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
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) {
|
public Bounds getBounds(Bounds bounds) {
|
||||||
bounds = super.getBounds(bounds);
|
bounds = super.getBounds(bounds);
|
||||||
bounds.addPoint(center);
|
bounds.addPoint(center);
|
||||||
circlePlane.recordBounds(bounds);
|
circlePlane.recordBounds(planetModel, bounds);
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,21 +227,20 @@ public class GeoCircle extends GeoBaseExtendedShape implements GeoDistanceShape,
|
||||||
if (!(o instanceof GeoCircle))
|
if (!(o instanceof GeoCircle))
|
||||||
return false;
|
return false;
|
||||||
GeoCircle other = (GeoCircle) o;
|
GeoCircle other = (GeoCircle) o;
|
||||||
return other.center.equals(center) && other.cutoffAngle == cutoffAngle;
|
return super.equals(other) && other.center.equals(center) && other.cutoffAngle == cutoffAngle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result;
|
int result = super.hashCode();
|
||||||
long temp;
|
result = 31 * result + center.hashCode();
|
||||||
result = center.hashCode();
|
long temp = Double.doubleToLongBits(cutoffAngle);
|
||||||
temp = Double.doubleToLongBits(cutoffAngle);
|
|
||||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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
|
* Create a convex polygon from a list of points. The first point must be on the
|
||||||
* external edge.
|
* external edge.
|
||||||
*/
|
*/
|
||||||
public GeoConvexPolygon(final List<GeoPoint> pointList) {
|
public GeoConvexPolygon(final PlanetModel planetModel, final List<GeoPoint> pointList) {
|
||||||
|
super(planetModel);
|
||||||
this.points = pointList;
|
this.points = pointList;
|
||||||
this.isInternalEdges = null;
|
this.isInternalEdges = null;
|
||||||
donePoints(false);
|
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
|
* 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.
|
* 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.points = pointList;
|
||||||
this.isInternalEdges = internalEdgeFlags;
|
this.isInternalEdges = internalEdgeFlags;
|
||||||
donePoints(returnEdgeInternal);
|
donePoints(returnEdgeInternal);
|
||||||
|
@ -65,7 +67,8 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
||||||
* Create a convex polygon, with a starting latitude and longitude.
|
* 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}
|
* 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>();
|
points = new ArrayList<GeoPoint>();
|
||||||
isInternalEdges = new BitSet();
|
isInternalEdges = new BitSet();
|
||||||
// Argument checking
|
// Argument checking
|
||||||
|
@ -74,7 +77,7 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
||||||
if (startLongitude < -Math.PI || startLongitude > Math.PI)
|
if (startLongitude < -Math.PI || startLongitude > Math.PI)
|
||||||
throw new IllegalArgumentException("Longitude out of range");
|
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);
|
points.add(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +97,7 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
||||||
if (longitude < -Math.PI || longitude > Math.PI)
|
if (longitude < -Math.PI || longitude > Math.PI)
|
||||||
throw new IllegalArgumentException("Longitude out of range");
|
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);
|
isInternalEdges.set(points.size(), isInternalEdge);
|
||||||
points.add(p);
|
points.add(p);
|
||||||
}
|
}
|
||||||
|
@ -191,7 +194,7 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
||||||
membershipBounds[count++] = edges[otherIndex];
|
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!");
|
//System.err.println(" intersects!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -230,7 +233,7 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
||||||
membershipBounds[count++] = edges[otherIndex];
|
membershipBounds[count++] = edges[otherIndex];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
edge.recordBounds(bounds, membershipBounds);
|
edge.recordBounds(planetModel, bounds, membershipBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fullDistance >= Math.PI) {
|
if (fullDistance >= Math.PI) {
|
||||||
|
@ -245,6 +248,8 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
||||||
if (!(o instanceof GeoConvexPolygon))
|
if (!(o instanceof GeoConvexPolygon))
|
||||||
return false;
|
return false;
|
||||||
GeoConvexPolygon other = (GeoConvexPolygon) o;
|
GeoConvexPolygon other = (GeoConvexPolygon) o;
|
||||||
|
if (!super.equals(other))
|
||||||
|
return false;
|
||||||
if (other.points.size() != points.size())
|
if (other.points.size() != points.size())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -257,17 +262,14 @@ public class GeoConvexPolygon extends GeoBaseExtendedShape implements GeoMembers
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return points.hashCode();
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + points.hashCode();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder edgeString = new StringBuilder("{");
|
return "GeoConvexPolygon: {planetmodel=" + planetModel + ", points=" + points + "}";
|
||||||
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 + "}";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
||||||
*
|
*
|
||||||
* @lucene.internal
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoDegenerateHorizontalLine extends GeoBBoxBase {
|
public class GeoDegenerateHorizontalLine extends GeoBaseBBox {
|
||||||
public final double latitude;
|
public final double latitude;
|
||||||
public final double leftLon;
|
public final double leftLon;
|
||||||
public final double rightLon;
|
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}
|
* 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
|
// Argument checking
|
||||||
if (latitude > Math.PI * 0.5 || latitude < -Math.PI * 0.5)
|
if (latitude > Math.PI * 0.5 || latitude < -Math.PI * 0.5)
|
||||||
throw new IllegalArgumentException("Latitude out of range");
|
throw new IllegalArgumentException("Latitude out of range");
|
||||||
|
@ -71,10 +72,10 @@ public class GeoDegenerateHorizontalLine extends GeoBBoxBase {
|
||||||
final double cosRightLon = Math.cos(rightLon);
|
final double cosRightLon = Math.cos(rightLon);
|
||||||
|
|
||||||
// Now build the two points
|
// Now build the two points
|
||||||
this.LHC = new GeoPoint(sinLatitude, sinLeftLon, cosLatitude, cosLeftLon);
|
this.LHC = new GeoPoint(planetModel, sinLatitude, sinLeftLon, cosLatitude, cosLeftLon);
|
||||||
this.RHC = new GeoPoint(sinLatitude, sinRightLon, cosLatitude, cosRightLon);
|
this.RHC = new GeoPoint(planetModel, sinLatitude, sinRightLon, cosLatitude, cosRightLon);
|
||||||
|
|
||||||
this.plane = new Plane(sinLatitude);
|
this.plane = new Plane(planetModel, sinLatitude);
|
||||||
|
|
||||||
// Normalize
|
// Normalize
|
||||||
while (leftLon > rightLon) {
|
while (leftLon > rightLon) {
|
||||||
|
@ -84,7 +85,7 @@ public class GeoDegenerateHorizontalLine extends GeoBBoxBase {
|
||||||
final double sinMiddleLon = Math.sin(middleLon);
|
final double sinMiddleLon = Math.sin(middleLon);
|
||||||
final double cosMiddleLon = Math.cos(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.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||||
|
|
||||||
|
@ -107,7 +108,7 @@ public class GeoDegenerateHorizontalLine extends GeoBBoxBase {
|
||||||
newLeftLon = -Math.PI;
|
newLeftLon = -Math.PI;
|
||||||
newRightLon = Math.PI;
|
newRightLon = Math.PI;
|
||||||
}
|
}
|
||||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -148,7 +149,7 @@ public class GeoDegenerateHorizontalLine extends GeoBBoxBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
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
|
@Override
|
||||||
public int getRelationship(final GeoShape path) {
|
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;
|
return OVERLAPS;
|
||||||
|
}
|
||||||
|
|
||||||
if (path.isWithin(centerPoint))
|
if (path.isWithin(centerPoint)) {
|
||||||
|
//System.err.println(" contains");
|
||||||
return CONTAINS;
|
return CONTAINS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//System.err.println(" disjoint");
|
||||||
return DISJOINT;
|
return DISJOINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,19 +191,20 @@ public class GeoDegenerateHorizontalLine extends GeoBBoxBase {
|
||||||
if (!(o instanceof GeoDegenerateHorizontalLine))
|
if (!(o instanceof GeoDegenerateHorizontalLine))
|
||||||
return false;
|
return false;
|
||||||
GeoDegenerateHorizontalLine other = (GeoDegenerateHorizontalLine) o;
|
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = LHC.hashCode();
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + LHC.hashCode();
|
||||||
result = 31 * result + RHC.hashCode();
|
result = 31 * result + RHC.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoDegenerateLatitudeZone extends GeoBBoxBase {
|
public class GeoDegenerateLatitudeZone extends GeoBaseBBox {
|
||||||
public final double latitude;
|
public final double latitude;
|
||||||
|
|
||||||
public final double sinLatitude;
|
public final double sinLatitude;
|
||||||
|
@ -32,14 +32,15 @@ public class GeoDegenerateLatitudeZone extends GeoBBoxBase {
|
||||||
public final GeoPoint[] edgePoints;
|
public final GeoPoint[] edgePoints;
|
||||||
public final static GeoPoint[] planePoints = new GeoPoint[0];
|
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.latitude = latitude;
|
||||||
|
|
||||||
this.sinLatitude = Math.sin(latitude);
|
this.sinLatitude = Math.sin(latitude);
|
||||||
double cosLatitude = Math.cos(latitude);
|
double cosLatitude = Math.cos(latitude);
|
||||||
this.plane = new Plane(sinLatitude);
|
this.plane = new Plane(planetModel, sinLatitude);
|
||||||
// Compute an interior point.
|
// 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};
|
edgePoints = new GeoPoint[]{interiorPoint};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +48,7 @@ public class GeoDegenerateLatitudeZone extends GeoBBoxBase {
|
||||||
public GeoBBox expand(final double angle) {
|
public GeoBBox expand(final double angle) {
|
||||||
double newTopLat = latitude + angle;
|
double newTopLat = latitude + angle;
|
||||||
double newBottomLat = 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
|
@Override
|
||||||
|
@ -83,7 +84,7 @@ public class GeoDegenerateLatitudeZone extends GeoBBoxBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
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))
|
if (!(o instanceof GeoDegenerateLatitudeZone))
|
||||||
return false;
|
return false;
|
||||||
GeoDegenerateLatitudeZone other = (GeoDegenerateLatitudeZone) o;
|
GeoDegenerateLatitudeZone other = (GeoDegenerateLatitudeZone) o;
|
||||||
return other.latitude == latitude;
|
return super.equals(other) && other.latitude == latitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
long temp = Double.doubleToLongBits(latitude);
|
long temp = Double.doubleToLongBits(latitude);
|
||||||
int result = (int) (temp ^ (temp >>> 32));
|
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoDegenerateLongitudeSlice extends GeoBBoxBase {
|
public class GeoDegenerateLongitudeSlice extends GeoBaseBBox {
|
||||||
public final double longitude;
|
public final double longitude;
|
||||||
|
|
||||||
public final double sinLongitude;
|
public final double sinLongitude;
|
||||||
|
@ -32,12 +32,13 @@ public class GeoDegenerateLongitudeSlice extends GeoBBoxBase {
|
||||||
public final GeoPoint interiorPoint;
|
public final GeoPoint interiorPoint;
|
||||||
public final GeoPoint[] edgePoints;
|
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}
|
* 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
|
// Argument checking
|
||||||
if (longitude < -Math.PI || longitude > Math.PI)
|
if (longitude < -Math.PI || longitude > Math.PI)
|
||||||
throw new IllegalArgumentException("Longitude out of range");
|
throw new IllegalArgumentException("Longitude out of range");
|
||||||
|
@ -48,9 +49,10 @@ public class GeoDegenerateLongitudeSlice extends GeoBBoxBase {
|
||||||
|
|
||||||
this.plane = new Plane(cosLongitude, sinLongitude);
|
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.
|
// 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.boundingPlane = new SidedPlane(interiorPoint, -sinLongitude, cosLongitude);
|
||||||
this.edgePoints = new GeoPoint[]{interiorPoint};
|
this.edgePoints = new GeoPoint[]{interiorPoint};
|
||||||
|
this.planePoints = new GeoPoint[]{planetModel.NORTH_POLE, planetModel.SOUTH_POLE};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -63,7 +65,7 @@ public class GeoDegenerateLongitudeSlice extends GeoBBoxBase {
|
||||||
newLeftLon = -Math.PI;
|
newLeftLon = -Math.PI;
|
||||||
newRightLon = 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
|
@Override
|
||||||
|
@ -100,7 +102,7 @@ public class GeoDegenerateLongitudeSlice extends GeoBBoxBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
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))
|
if (!(o instanceof GeoDegenerateLongitudeSlice))
|
||||||
return false;
|
return false;
|
||||||
GeoDegenerateLongitudeSlice other = (GeoDegenerateLongitudeSlice) o;
|
GeoDegenerateLongitudeSlice other = (GeoDegenerateLongitudeSlice) o;
|
||||||
return other.longitude == longitude;
|
return super.equals(other) && other.longitude == longitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result;
|
int result = super.hashCode();
|
||||||
long temp;
|
long temp = Double.doubleToLongBits(longitude);
|
||||||
temp = Double.doubleToLongBits(longitude);
|
result = result * 31 + (int) (temp ^ (temp >>> 32));
|
||||||
result = (int) (temp ^ (temp >>> 32));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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 class GeoDegeneratePoint extends GeoPoint implements GeoBBox {
|
||||||
public final double latitude;
|
public final double latitude;
|
||||||
public final double longitude;
|
public final double longitude;
|
||||||
|
public final PlanetModel planetModel;
|
||||||
public final GeoPoint[] edgePoints;
|
public final GeoPoint[] edgePoints;
|
||||||
|
|
||||||
public GeoDegeneratePoint(final double lat, final double lon) {
|
public GeoDegeneratePoint(final PlanetModel planetModel, final double lat, final double lon) {
|
||||||
super(lat, lon);
|
super(planetModel, lat, lon);
|
||||||
|
this.planetModel = planetModel;
|
||||||
this.latitude = lat;
|
this.latitude = lat;
|
||||||
this.longitude = lon;
|
this.longitude = lon;
|
||||||
this.edgePoints = new GeoPoint[]{this};
|
this.edgePoints = new GeoPoint[]{this};
|
||||||
|
@ -47,7 +49,7 @@ public class GeoDegeneratePoint extends GeoPoint implements GeoBBox {
|
||||||
final double newBottomLat = latitude - angle;
|
final double newBottomLat = latitude - angle;
|
||||||
final double newLeftLon = longitude - angle;
|
final double newLeftLon = longitude - angle;
|
||||||
final double newRightLon = 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))
|
if (!(o instanceof GeoDegeneratePoint))
|
||||||
return false;
|
return false;
|
||||||
GeoDegeneratePoint other = (GeoDegeneratePoint) o;
|
GeoDegeneratePoint other = (GeoDegeneratePoint) o;
|
||||||
return other.latitude == latitude && other.longitude == longitude;
|
return super.equals(other) && other.latitude == latitude && other.longitude == longitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result;
|
int result = super.hashCode();
|
||||||
long temp;
|
long temp = Double.doubleToLongBits(latitude);
|
||||||
temp = Double.doubleToLongBits(latitude);
|
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||||
result = (int) (temp ^ (temp >>> 32));
|
|
||||||
temp = Double.doubleToLongBits(longitude);
|
temp = Double.doubleToLongBits(longitude);
|
||||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||||
return result;
|
return result;
|
||||||
|
@ -124,7 +125,7 @@ public class GeoDegeneratePoint extends GeoPoint implements GeoBBox {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoDegenerateVerticalLine extends GeoBBoxBase {
|
public class GeoDegenerateVerticalLine extends GeoBaseBBox {
|
||||||
public final double topLat;
|
public final double topLat;
|
||||||
public final double bottomLat;
|
public final double bottomLat;
|
||||||
public final double longitude;
|
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}
|
* 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
|
// Argument checking
|
||||||
if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
|
if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
|
||||||
throw new IllegalArgumentException("Top latitude out of range");
|
throw new IllegalArgumentException("Top latitude out of range");
|
||||||
|
@ -66,8 +67,8 @@ public class GeoDegenerateVerticalLine extends GeoBBoxBase {
|
||||||
final double cosLongitude = Math.cos(longitude);
|
final double cosLongitude = Math.cos(longitude);
|
||||||
|
|
||||||
// Now build the two points
|
// Now build the two points
|
||||||
this.UHC = new GeoPoint(sinTopLat, sinLongitude, cosTopLat, cosLongitude);
|
this.UHC = new GeoPoint(planetModel, sinTopLat, sinLongitude, cosTopLat, cosLongitude);
|
||||||
this.LHC = new GeoPoint(sinBottomLat, sinLongitude, cosBottomLat, cosLongitude);
|
this.LHC = new GeoPoint(planetModel, sinBottomLat, sinLongitude, cosBottomLat, cosLongitude);
|
||||||
|
|
||||||
this.plane = new Plane(cosLongitude, sinLongitude);
|
this.plane = new Plane(cosLongitude, sinLongitude);
|
||||||
|
|
||||||
|
@ -75,10 +76,10 @@ public class GeoDegenerateVerticalLine extends GeoBBoxBase {
|
||||||
final double sinMiddleLat = Math.sin(middleLat);
|
final double sinMiddleLat = Math.sin(middleLat);
|
||||||
final double cosMiddleLat = Math.cos(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.topPlane = new SidedPlane(centerPoint, planetModel, sinTopLat);
|
||||||
this.bottomPlane = new SidedPlane(centerPoint, sinBottomLat);
|
this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
|
||||||
|
|
||||||
this.boundingPlane = new SidedPlane(centerPoint, -sinLongitude, cosLongitude);
|
this.boundingPlane = new SidedPlane(centerPoint, -sinLongitude, cosLongitude);
|
||||||
|
|
||||||
|
@ -98,7 +99,7 @@ public class GeoDegenerateVerticalLine extends GeoBBoxBase {
|
||||||
newLeftLon = -Math.PI;
|
newLeftLon = -Math.PI;
|
||||||
newRightLon = Math.PI;
|
newRightLon = Math.PI;
|
||||||
}
|
}
|
||||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -144,7 +145,7 @@ public class GeoDegenerateVerticalLine extends GeoBBoxBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
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))
|
if (!(o instanceof GeoDegenerateVerticalLine))
|
||||||
return false;
|
return false;
|
||||||
GeoDegenerateVerticalLine other = (GeoDegenerateVerticalLine) o;
|
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = UHC.hashCode();
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + UHC.hashCode();
|
||||||
result = 31 * result + LHC.hashCode();
|
result = 31 * result + LHC.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
||||||
*
|
*
|
||||||
* @lucene.internal
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoLatitudeZone extends GeoBBoxBase {
|
public class GeoLatitudeZone extends GeoBaseBBox {
|
||||||
public final double topLat;
|
public final double topLat;
|
||||||
public final double bottomLat;
|
public final double bottomLat;
|
||||||
public final double cosTopLat;
|
public final double cosTopLat;
|
||||||
|
@ -40,7 +40,8 @@ public class GeoLatitudeZone extends GeoBBoxBase {
|
||||||
// Edge points
|
// Edge points
|
||||||
public final GeoPoint[] edgePoints;
|
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.topLat = topLat;
|
||||||
this.bottomLat = bottomLat;
|
this.bottomLat = bottomLat;
|
||||||
|
|
||||||
|
@ -49,19 +50,15 @@ public class GeoLatitudeZone extends GeoBBoxBase {
|
||||||
this.cosTopLat = Math.cos(topLat);
|
this.cosTopLat = Math.cos(topLat);
|
||||||
this.cosBottomLat = Math.cos(bottomLat);
|
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.
|
// Compute an interior point. Pick one whose lat is between top and bottom.
|
||||||
final double middleLat = (topLat + bottomLat) * 0.5;
|
final double middleLat = (topLat + bottomLat) * 0.5;
|
||||||
final double sinMiddleLat = Math.sin(middleLat);
|
final double sinMiddleLat = Math.sin(middleLat);
|
||||||
this.interiorPoint = new GeoPoint(Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 0.0, sinMiddleLat);
|
this.interiorPoint = new GeoPoint(planetModel, sinMiddleLat, 0.0, Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 1.0);
|
||||||
this.topBoundaryPoint = new GeoPoint(Math.sqrt(1.0 - sinTopLat * sinTopLat), 0.0, sinTopLat);
|
this.topBoundaryPoint = new GeoPoint(planetModel, sinTopLat, 0.0, Math.sqrt(1.0 - sinTopLat * sinTopLat), 1.0);
|
||||||
this.bottomBoundaryPoint = new GeoPoint(Math.sqrt(1.0 - sinBottomLat * sinBottomLat), 0.0, sinBottomLat);
|
this.bottomBoundaryPoint = new GeoPoint(planetModel, sinBottomLat, 0.0, Math.sqrt(1.0 - sinBottomLat * sinBottomLat), 1.0);
|
||||||
|
|
||||||
this.topPlane = new SidedPlane(interiorPoint, sinTopLat);
|
this.topPlane = new SidedPlane(interiorPoint, planetModel, sinTopLat);
|
||||||
this.bottomPlane = new SidedPlane(interiorPoint, sinBottomLat);
|
this.bottomPlane = new SidedPlane(interiorPoint, planetModel, sinBottomLat);
|
||||||
|
|
||||||
this.edgePoints = new GeoPoint[]{topBoundaryPoint, bottomBoundaryPoint};
|
this.edgePoints = new GeoPoint[]{topBoundaryPoint, bottomBoundaryPoint};
|
||||||
}
|
}
|
||||||
|
@ -70,7 +67,7 @@ public class GeoLatitudeZone extends GeoBBoxBase {
|
||||||
public GeoBBox expand(final double angle) {
|
public GeoBBox expand(final double angle) {
|
||||||
final double newTopLat = topLat + angle;
|
final double newTopLat = topLat + angle;
|
||||||
final double newBottomLat = bottomLat - 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
|
@Override
|
||||||
|
@ -115,8 +112,8 @@ public class GeoLatitudeZone extends GeoBBoxBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||||
return p.intersects(topPlane, notablePoints, planePoints, bounds, bottomPlane) ||
|
return p.intersects(planetModel, topPlane, notablePoints, planePoints, bounds, bottomPlane) ||
|
||||||
p.intersects(bottomPlane, notablePoints, planePoints, bounds, topPlane);
|
p.intersects(planetModel, bottomPlane, notablePoints, planePoints, bounds, topPlane);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -181,18 +178,19 @@ public class GeoLatitudeZone extends GeoBBoxBase {
|
||||||
if (!(o instanceof GeoLatitudeZone))
|
if (!(o instanceof GeoLatitudeZone))
|
||||||
return false;
|
return false;
|
||||||
GeoLatitudeZone other = (GeoLatitudeZone) o;
|
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = topPlane.hashCode();
|
int result = super.hashCode();
|
||||||
result = 31 * result + bottomPlane.hashCode();
|
result = 31 * result + topBoundaryPoint.hashCode();
|
||||||
|
result = 31 * result + bottomBoundaryPoint.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoLongitudeSlice extends GeoBBoxBase {
|
public class GeoLongitudeSlice extends GeoBaseBBox {
|
||||||
public final double leftLon;
|
public final double leftLon;
|
||||||
public final double rightLon;
|
public final double rightLon;
|
||||||
|
|
||||||
public final SidedPlane leftPlane;
|
public final SidedPlane leftPlane;
|
||||||
public final SidedPlane rightPlane;
|
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 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}
|
* 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
|
// Argument checking
|
||||||
if (leftLon < -Math.PI || leftLon > Math.PI)
|
if (leftLon < -Math.PI || leftLon > Math.PI)
|
||||||
throw new IllegalArgumentException("Left longitude out of range");
|
throw new IllegalArgumentException("Left longitude out of range");
|
||||||
|
@ -66,11 +67,13 @@ public class GeoLongitudeSlice extends GeoBBoxBase {
|
||||||
rightLon += Math.PI * 2.0;
|
rightLon += Math.PI * 2.0;
|
||||||
}
|
}
|
||||||
final double middleLon = (leftLon + rightLon) * 0.5;
|
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.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
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
|
@Override
|
||||||
|
@ -85,7 +88,7 @@ public class GeoLongitudeSlice extends GeoBBoxBase {
|
||||||
newLeftLon = -Math.PI;
|
newLeftLon = -Math.PI;
|
||||||
newRightLon = 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
|
@Override
|
||||||
|
@ -126,8 +129,8 @@ public class GeoLongitudeSlice extends GeoBBoxBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||||
return p.intersects(leftPlane, notablePoints, planePoints, bounds, rightPlane) ||
|
return p.intersects(planetModel, leftPlane, notablePoints, planePoints, bounds, rightPlane) ||
|
||||||
p.intersects(rightPlane, notablePoints, planePoints, bounds, leftPlane);
|
p.intersects(planetModel, rightPlane, notablePoints, planePoints, bounds, leftPlane);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -154,7 +157,7 @@ public class GeoLongitudeSlice extends GeoBBoxBase {
|
||||||
if (insideRectangle == SOME_INSIDE)
|
if (insideRectangle == SOME_INSIDE)
|
||||||
return OVERLAPS;
|
return OVERLAPS;
|
||||||
|
|
||||||
final boolean insideShape = path.isWithin(NORTH_POLE);
|
final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
|
||||||
|
|
||||||
if (insideRectangle == ALL_INSIDE && insideShape)
|
if (insideRectangle == ALL_INSIDE && insideShape)
|
||||||
return OVERLAPS;
|
return OVERLAPS;
|
||||||
|
@ -180,15 +183,14 @@ public class GeoLongitudeSlice extends GeoBBoxBase {
|
||||||
if (!(o instanceof GeoLongitudeSlice))
|
if (!(o instanceof GeoLongitudeSlice))
|
||||||
return false;
|
return false;
|
||||||
GeoLongitudeSlice other = (GeoLongitudeSlice) o;
|
GeoLongitudeSlice other = (GeoLongitudeSlice) o;
|
||||||
return other.leftLon == leftLon && other.rightLon == rightLon;
|
return super.equals(other) && other.leftLon == leftLon && other.rightLon == rightLon;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result;
|
int result = super.hashCode();
|
||||||
long temp;
|
long temp = Double.doubleToLongBits(leftLon);
|
||||||
temp = Double.doubleToLongBits(leftLon);
|
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||||
result = (int) (temp ^ (temp >>> 32));
|
|
||||||
temp = Double.doubleToLongBits(rightLon);
|
temp = Double.doubleToLongBits(rightLon);
|
||||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||||
return result;
|
return result;
|
||||||
|
@ -196,7 +198,7 @@ public class GeoLongitudeSlice extends GeoBBoxBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoNorthLatitudeZone extends GeoBBoxBase {
|
public class GeoNorthLatitudeZone extends GeoBaseBBox {
|
||||||
public final double bottomLat;
|
public final double bottomLat;
|
||||||
public final double cosBottomLat;
|
public final double cosBottomLat;
|
||||||
public final SidedPlane bottomPlane;
|
public final SidedPlane bottomPlane;
|
||||||
|
@ -34,22 +34,20 @@ public class GeoNorthLatitudeZone extends GeoBBoxBase {
|
||||||
// Edge points
|
// Edge points
|
||||||
public final GeoPoint[] edgePoints;
|
public final GeoPoint[] edgePoints;
|
||||||
|
|
||||||
public GeoNorthLatitudeZone(final double bottomLat) {
|
public GeoNorthLatitudeZone(final PlanetModel planetModel, final double bottomLat) {
|
||||||
|
super(planetModel);
|
||||||
this.bottomLat = bottomLat;
|
this.bottomLat = bottomLat;
|
||||||
|
|
||||||
final double sinBottomLat = Math.sin(bottomLat);
|
final double sinBottomLat = Math.sin(bottomLat);
|
||||||
this.cosBottomLat = Math.cos(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.
|
// 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 middleLat = (Math.PI * 0.5 + bottomLat) * 0.5;
|
||||||
final double sinMiddleLat = Math.sin(middleLat);
|
final double sinMiddleLat = Math.sin(middleLat);
|
||||||
this.interiorPoint = new GeoPoint(Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 0.0, sinMiddleLat);
|
this.interiorPoint = new GeoPoint(planetModel, sinMiddleLat, 0.0, Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 1.0);
|
||||||
this.bottomBoundaryPoint = new GeoPoint(Math.sqrt(1.0 - sinBottomLat * sinBottomLat), 0.0, sinBottomLat);
|
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};
|
this.edgePoints = new GeoPoint[]{bottomBoundaryPoint};
|
||||||
}
|
}
|
||||||
|
@ -58,7 +56,7 @@ public class GeoNorthLatitudeZone extends GeoBBoxBase {
|
||||||
public GeoBBox expand(final double angle) {
|
public GeoBBox expand(final double angle) {
|
||||||
final double newTopLat = Math.PI * 0.5;
|
final double newTopLat = Math.PI * 0.5;
|
||||||
final double newBottomLat = bottomLat - 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
|
@Override
|
||||||
|
@ -101,7 +99,7 @@ public class GeoNorthLatitudeZone extends GeoBBoxBase {
|
||||||
@Override
|
@Override
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||||
return
|
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))
|
if (!(o instanceof GeoNorthLatitudeZone))
|
||||||
return false;
|
return false;
|
||||||
GeoNorthLatitudeZone other = (GeoNorthLatitudeZone) o;
|
GeoNorthLatitudeZone other = (GeoNorthLatitudeZone) o;
|
||||||
return other.bottomPlane.equals(bottomPlane);
|
return super.equals(other) && other.bottomBoundaryPoint.equals(bottomBoundaryPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = bottomPlane.hashCode();
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + bottomBoundaryPoint.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoNorthRectangle extends GeoBBoxBase {
|
public class GeoNorthRectangle extends GeoBaseBBox {
|
||||||
public final double bottomLat;
|
public final double bottomLat;
|
||||||
public final double leftLon;
|
public final double leftLon;
|
||||||
public final double rightLon;
|
public final double rightLon;
|
||||||
|
@ -45,12 +45,13 @@ public class GeoNorthRectangle extends GeoBBoxBase {
|
||||||
|
|
||||||
public final GeoPoint centerPoint;
|
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}
|
* 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
|
// Argument checking
|
||||||
if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
|
if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
|
||||||
throw new IllegalArgumentException("Bottom latitude out of range");
|
throw new IllegalArgumentException("Bottom latitude out of range");
|
||||||
|
@ -77,8 +78,8 @@ public class GeoNorthRectangle extends GeoBBoxBase {
|
||||||
final double cosRightLon = Math.cos(rightLon);
|
final double cosRightLon = Math.cos(rightLon);
|
||||||
|
|
||||||
// Now build the points
|
// Now build the points
|
||||||
this.LRHC = new GeoPoint(sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
|
this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
|
||||||
this.LLHC = new GeoPoint(sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
|
this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
|
||||||
|
|
||||||
final double middleLat = (Math.PI * 0.5 + bottomLat) * 0.5;
|
final double middleLat = (Math.PI * 0.5 + bottomLat) * 0.5;
|
||||||
final double sinMiddleLat = Math.sin(middleLat);
|
final double sinMiddleLat = Math.sin(middleLat);
|
||||||
|
@ -91,16 +92,17 @@ public class GeoNorthRectangle extends GeoBBoxBase {
|
||||||
final double sinMiddleLon = Math.sin(middleLon);
|
final double sinMiddleLon = Math.sin(middleLon);
|
||||||
final double cosMiddleLon = Math.cos(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.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||||
|
|
||||||
this.bottomPlanePoints = new GeoPoint[]{LLHC, LRHC};
|
this.bottomPlanePoints = new GeoPoint[]{LLHC, LRHC};
|
||||||
this.leftPlanePoints = new GeoPoint[]{NORTH_POLE, LLHC};
|
this.leftPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LLHC};
|
||||||
this.rightPlanePoints = new GeoPoint[]{NORTH_POLE, LRHC};
|
this.rightPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LRHC};
|
||||||
|
|
||||||
|
this.edgePoints = new GeoPoint[]{planetModel.NORTH_POLE};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -117,7 +119,7 @@ public class GeoNorthRectangle extends GeoBBoxBase {
|
||||||
newLeftLon = -Math.PI;
|
newLeftLon = -Math.PI;
|
||||||
newRightLon = Math.PI;
|
newRightLon = Math.PI;
|
||||||
}
|
}
|
||||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -164,9 +166,9 @@ public class GeoNorthRectangle extends GeoBBoxBase {
|
||||||
@Override
|
@Override
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||||
return
|
return
|
||||||
p.intersects(bottomPlane, notablePoints, bottomPlanePoints, bounds, leftPlane, rightPlane) ||
|
p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, leftPlane, rightPlane) ||
|
||||||
p.intersects(leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, bottomPlane) ||
|
p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, bottomPlane) ||
|
||||||
p.intersects(rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, bottomPlane);
|
p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, bottomPlane);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -196,7 +198,7 @@ public class GeoNorthRectangle extends GeoBBoxBase {
|
||||||
return OVERLAPS;
|
return OVERLAPS;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean insideShape = path.isWithin(NORTH_POLE);
|
final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
|
||||||
|
|
||||||
if (insideRectangle == ALL_INSIDE && insideShape) {
|
if (insideRectangle == ALL_INSIDE && insideShape) {
|
||||||
//System.err.println(" inside of each other");
|
//System.err.println(" inside of each other");
|
||||||
|
@ -229,19 +231,20 @@ public class GeoNorthRectangle extends GeoBBoxBase {
|
||||||
if (!(o instanceof GeoNorthRectangle))
|
if (!(o instanceof GeoNorthRectangle))
|
||||||
return false;
|
return false;
|
||||||
GeoNorthRectangle other = (GeoNorthRectangle) o;
|
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = LLHC.hashCode();
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + LLHC.hashCode();
|
||||||
result = 31 * result + LRHC.hashCode();
|
result = 31 * result + LRHC.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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
|
* @lucene.experimental
|
||||||
*/
|
*/
|
||||||
public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
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 List<SegmentEndpoint> points = new ArrayList<SegmentEndpoint>();
|
public final double cutoffAngle;
|
||||||
|
public final double sinAngle;
|
||||||
|
public final double cosAngle;
|
||||||
|
|
||||||
|
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 final List<PathSegment> segments = new ArrayList<PathSegment>();
|
||||||
|
|
||||||
public GeoPoint[] edgePoints = null;
|
public GeoPoint[] edgePoints = null;
|
||||||
|
|
||||||
public GeoPath(final double cutoffAngle) {
|
public GeoPath(final PlanetModel planetModel, final double maxCutoffAngle) {
|
||||||
super();
|
super(planetModel);
|
||||||
if (cutoffAngle <= 0.0 || cutoffAngle > Math.PI * 0.5)
|
if (maxCutoffAngle <= 0.0 || maxCutoffAngle > Math.PI * 0.5)
|
||||||
throw new IllegalArgumentException("Cutoff angle out of bounds");
|
throw new IllegalArgumentException("Cutoff angle out of bounds");
|
||||||
this.cutoffAngle = cutoffAngle;
|
this.cutoffAngle = maxCutoffAngle;
|
||||||
final double cosAngle = Math.cos(cutoffAngle);
|
this.cosAngle = Math.cos(maxCutoffAngle);
|
||||||
final double sinAngle = Math.sin(cutoffAngle);
|
this.sinAngle = Math.sin(maxCutoffAngle);
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPoint(double lat, double lon) {
|
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");
|
throw new IllegalArgumentException("Latitude out of range");
|
||||||
if (lon < -Math.PI || lon > Math.PI)
|
if (lon < -Math.PI || lon > Math.PI)
|
||||||
throw new IllegalArgumentException("Longitude out of range");
|
throw new IllegalArgumentException("Longitude out of range");
|
||||||
final GeoPoint end = new GeoPoint(lat, lon);
|
points.add(new GeoPoint(planetModel, 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void done() {
|
public void done() {
|
||||||
if (points.size() == 0)
|
if (points.size() == 0)
|
||||||
throw new IllegalArgumentException("Path must have at least one point");
|
throw new IllegalArgumentException("Path must have at least one point");
|
||||||
if (segments.size() > 0) {
|
// Compute an offset to use for all segments. This will be based on the minimum magnitude of
|
||||||
edgePoints = new GeoPoint[]{points.get(0).circlePlane.getSampleIntersectionPoint(segments.get(0).invertedStartCutoffPlane)};
|
// 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;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < points.size(); i++) {
|
segments.add(new PathSegment(planetModel, lastPoint, end, normalizedConnectingPlane, cutoffOffset));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
if (i < segments.size()) {
|
lastPoint = end;
|
||||||
final PathSegment nextSegment = segments.get(i);
|
|
||||||
nextStartBound = nextSegment.invertedStartCutoffPlane;
|
|
||||||
nextStartNotablePoints = nextSegment.startCutoffPlanePoints;
|
|
||||||
}
|
}
|
||||||
pathPoint.setCutoffPlanes(previousEndNotablePoints, previousEndBound, nextStartNotablePoints, nextStartBound);
|
|
||||||
|
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;
|
int segmentIndex = 0;
|
||||||
currentDistance = 0.0;
|
currentDistance = 0.0;
|
||||||
for (SegmentEndpoint endpoint : points) {
|
for (SegmentEndpoint endpoint : endPoints) {
|
||||||
double distance = endpoint.pathNormalDistance(point);
|
double distance = endpoint.pathNormalDistance(point);
|
||||||
if (distance != Double.MAX_VALUE)
|
if (distance != Double.MAX_VALUE)
|
||||||
return currentDistance + distance;
|
return currentDistance + distance;
|
||||||
|
@ -194,7 +213,7 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
||||||
|
|
||||||
int segmentIndex = 0;
|
int segmentIndex = 0;
|
||||||
currentDistance = 0.0;
|
currentDistance = 0.0;
|
||||||
for (SegmentEndpoint endpoint : points) {
|
for (SegmentEndpoint endpoint : endPoints) {
|
||||||
double distance = endpoint.pathLinearDistance(point);
|
double distance = endpoint.pathLinearDistance(point);
|
||||||
if (distance != Double.MAX_VALUE)
|
if (distance != Double.MAX_VALUE)
|
||||||
return currentDistance + distance;
|
return currentDistance + distance;
|
||||||
|
@ -251,7 +270,7 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
||||||
|
|
||||||
int segmentIndex = 0;
|
int segmentIndex = 0;
|
||||||
currentDistance = 0.0;
|
currentDistance = 0.0;
|
||||||
for (SegmentEndpoint endpoint : points) {
|
for (SegmentEndpoint endpoint : endPoints) {
|
||||||
double distance = endpoint.pathDistance(point);
|
double distance = endpoint.pathDistance(point);
|
||||||
if (distance != Double.MAX_VALUE)
|
if (distance != Double.MAX_VALUE)
|
||||||
return currentDistance + distance;
|
return currentDistance + distance;
|
||||||
|
@ -264,20 +283,26 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isWithin(final Vector point) {
|
public boolean isWithin(final Vector point) {
|
||||||
for (SegmentEndpoint pathPoint : points) {
|
//System.err.println("Assessing whether point "+point+" is within geopath "+this);
|
||||||
if (pathPoint.isWithin(point))
|
for (SegmentEndpoint pathPoint : endPoints) {
|
||||||
|
if (pathPoint.isWithin(point)) {
|
||||||
|
//System.err.println(" point is within SegmentEndpoint "+pathPoint);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for (PathSegment pathSegment : segments) {
|
for (PathSegment pathSegment : segments) {
|
||||||
if (pathSegment.isWithin(point))
|
if (pathSegment.isWithin(point)) {
|
||||||
|
//System.err.println(" point is within PathSegment "+pathSegment);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
//System.err.println(" point is not within geopath");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isWithin(final double x, final double y, final double z) {
|
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))
|
if (pathPoint.isWithin(x, y, z))
|
||||||
return true;
|
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.
|
// 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.
|
// 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.
|
// But that's an edge case and we won't be optimizing for it.
|
||||||
|
//System.err.println(" Looking for intersection of plane "+plane+" with path "+this);
|
||||||
for (final SegmentEndpoint pathPoint : points) {
|
for (final SegmentEndpoint pathPoint : endPoints) {
|
||||||
if (pathPoint.intersects(plane, notablePoints, bounds)) {
|
if (pathPoint.intersects(planetModel, plane, notablePoints, bounds)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final PathSegment pathSegment : segments) {
|
for (final PathSegment pathSegment : segments) {
|
||||||
if (pathSegment.intersects(plane, notablePoints, bounds)) {
|
if (pathSegment.intersects(planetModel, plane, notablePoints, bounds)) {
|
||||||
return true;
|
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
|
// never more than 180 degrees longitude at a pop or we risk having the
|
||||||
// bounds object get itself inverted. So do the edges first.
|
// bounds object get itself inverted. So do the edges first.
|
||||||
for (PathSegment pathSegment : segments) {
|
for (PathSegment pathSegment : segments) {
|
||||||
pathSegment.getBounds(bounds);
|
pathSegment.getBounds(planetModel, bounds);
|
||||||
}
|
}
|
||||||
for (SegmentEndpoint pathPoint : points) {
|
for (SegmentEndpoint pathPoint : endPoints) {
|
||||||
pathPoint.getBounds(bounds);
|
pathPoint.getBounds(planetModel, bounds);
|
||||||
}
|
}
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
@ -349,13 +374,15 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
||||||
if (!(o instanceof GeoPath))
|
if (!(o instanceof GeoPath))
|
||||||
return false;
|
return false;
|
||||||
GeoPath p = (GeoPath) o;
|
GeoPath p = (GeoPath) o;
|
||||||
if (points.size() != p.points.size())
|
if (!super.equals(p))
|
||||||
|
return false;
|
||||||
|
if (endPoints.size() != p.endPoints.size())
|
||||||
return false;
|
return false;
|
||||||
if (cutoffAngle != p.cutoffAngle)
|
if (cutoffAngle != p.cutoffAngle)
|
||||||
return false;
|
return false;
|
||||||
for (int i = 0; i < points.size(); i++) {
|
for (int i = 0; i < endPoints.size(); i++) {
|
||||||
SegmentEndpoint point = points.get(i);
|
SegmentEndpoint point = endPoints.get(i);
|
||||||
SegmentEndpoint point2 = p.points.get(i);
|
SegmentEndpoint point2 = p.endPoints.get(i);
|
||||||
if (!point.equals(point2))
|
if (!point.equals(point2))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -364,101 +391,168 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result;
|
int result = super.hashCode();
|
||||||
long temp;
|
long temp = Double.doubleToLongBits(cutoffAngle);
|
||||||
temp = Double.doubleToLongBits(cutoffAngle);
|
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||||
result = (int) (temp ^ (temp >>> 32));
|
result = 31 * result + endPoints.hashCode();
|
||||||
result = 31 * result + points.hashCode();
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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.
|
* 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 static class SegmentEndpoint {
|
||||||
public final GeoPoint point;
|
public final GeoPoint point;
|
||||||
public final SidedPlane circlePlane;
|
public final SidedPlane circlePlane;
|
||||||
public final double cutoffNormalDistance;
|
public final Membership[] cutoffPlanes;
|
||||||
public final double cutoffAngle;
|
public final GeoPoint[] notablePoints;
|
||||||
public final double chordDistance;
|
|
||||||
public Membership[] cutoffPlanes = null;
|
|
||||||
public GeoPoint[] notablePoints = null;
|
|
||||||
|
|
||||||
public final static GeoPoint[] circlePoints = new GeoPoint[0];
|
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.point = point;
|
||||||
this.cutoffNormalDistance = cutoffOffset;
|
this.circlePlane = null;
|
||||||
this.cutoffAngle = cutoffAngle;
|
this.cutoffPlanes = null;
|
||||||
this.chordDistance = chordDistance;
|
this.notablePoints = null;
|
||||||
this.circlePlane = new SidedPlane(point, point, -originDistance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCutoffPlanes(final GeoPoint[] previousEndNotablePoints, final Membership previousEndPlane,
|
/** Constructor for case (1).
|
||||||
final GeoPoint[] nextStartNotablePoints, final Membership nextStartPlane) {
|
* Generate a simple circle cutoff plane.
|
||||||
if (previousEndNotablePoints == null && nextStartNotablePoints == null) {
|
*/
|
||||||
cutoffPlanes = new Membership[0];
|
public SegmentEndpoint(final GeoPoint point, final double cutoffOffset) {
|
||||||
notablePoints = new GeoPoint[0];
|
this.point = point;
|
||||||
} else if (previousEndNotablePoints != null && nextStartNotablePoints == null) {
|
final double magnitude = point.magnitude();
|
||||||
cutoffPlanes = new Membership[]{previousEndPlane};
|
// Normalize vector to make D value correct
|
||||||
notablePoints = previousEndNotablePoints;
|
this.circlePlane = new SidedPlane(point, point.normalize(), -Math.sqrt(magnitude * magnitude - cutoffOffset * cutoffOffset));
|
||||||
} else if (previousEndNotablePoints == null && nextStartNotablePoints != null) {
|
this.cutoffPlanes = new Membership[0];
|
||||||
cutoffPlanes = new Membership[]{nextStartPlane};
|
this.notablePoints = new GeoPoint[0];
|
||||||
notablePoints = nextStartNotablePoints;
|
}
|
||||||
|
|
||||||
|
/** 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);
|
||||||
|
|
||||||
|
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 {
|
} else {
|
||||||
cutoffPlanes = new Membership[]{previousEndPlane, nextStartPlane};
|
// dunno what happened
|
||||||
notablePoints = new GeoPoint[previousEndNotablePoints.length + nextStartNotablePoints.length];
|
throw new RuntimeException("Couldn't come up with a plane through three points that included the fourth");
|
||||||
int i = 0;
|
|
||||||
for (GeoPoint p : previousEndNotablePoints) {
|
|
||||||
notablePoints[i++] = p;
|
|
||||||
}
|
|
||||||
for (GeoPoint p : nextStartNotablePoints) {
|
|
||||||
notablePoints[i++] = p;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWithin(final Vector point) {
|
public boolean isWithin(final Vector point) {
|
||||||
|
if (circlePlane == null)
|
||||||
|
return false;
|
||||||
return circlePlane.isWithin(point);
|
return circlePlane.isWithin(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWithin(final double x, final double y, final double z) {
|
public boolean isWithin(final double x, final double y, final double z) {
|
||||||
|
if (circlePlane == null)
|
||||||
|
return false;
|
||||||
return circlePlane.isWithin(x, y, z);
|
return circlePlane.isWithin(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double pathDistance(final GeoPoint point) {
|
public double pathDistance(final GeoPoint point) {
|
||||||
double dist = this.point.arcDistance(point);
|
if (!isWithin(point))
|
||||||
if (dist > cutoffAngle)
|
|
||||||
return Double.MAX_VALUE;
|
return Double.MAX_VALUE;
|
||||||
return dist;
|
return this.point.arcDistance(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double pathNormalDistance(final GeoPoint point) {
|
public double pathNormalDistance(final GeoPoint point) {
|
||||||
double dist = this.point.normalDistance(point);
|
if (!isWithin(point))
|
||||||
if (dist > cutoffNormalDistance)
|
|
||||||
return Double.MAX_VALUE;
|
return Double.MAX_VALUE;
|
||||||
return dist;
|
return this.point.normalDistance(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double pathLinearDistance(final GeoPoint point) {
|
public double pathLinearDistance(final GeoPoint point) {
|
||||||
double dist = this.point.linearDistance(point);
|
if (!isWithin(point))
|
||||||
if (dist > chordDistance)
|
|
||||||
return Double.MAX_VALUE;
|
return Double.MAX_VALUE;
|
||||||
return dist;
|
return this.point.linearDistance(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
|
public boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
|
||||||
return circlePlane.intersects(p, notablePoints, this.notablePoints, bounds, this.cutoffPlanes);
|
//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);
|
bounds.addPoint(point);
|
||||||
circlePlane.recordBounds(bounds);
|
if (circlePlane == null)
|
||||||
|
return;
|
||||||
|
circlePlane.recordBounds(planetModel, bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -494,41 +588,26 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
||||||
public final SidedPlane lowerConnectingPlane;
|
public final SidedPlane lowerConnectingPlane;
|
||||||
public final SidedPlane startCutoffPlane;
|
public final SidedPlane startCutoffPlane;
|
||||||
public final SidedPlane endCutoffPlane;
|
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[] upperConnectingPlanePoints;
|
||||||
public final GeoPoint[] lowerConnectingPlanePoints;
|
public final GeoPoint[] lowerConnectingPlanePoints;
|
||||||
public final GeoPoint[] startCutoffPlanePoints;
|
public final GeoPoint[] startCutoffPlanePoints;
|
||||||
public final GeoPoint[] endCutoffPlanePoints;
|
public final GeoPoint[] endCutoffPlanePoints;
|
||||||
public final double planeBoundingOffset;
|
public final double planeBoundingOffset;
|
||||||
public final double arcWidth;
|
|
||||||
public final double chordDistance;
|
|
||||||
|
|
||||||
// For the adjoining SegmentEndpoint...
|
public PathSegment(final PlanetModel planetModel, final GeoPoint start, final GeoPoint end,
|
||||||
public final SidedPlane invertedStartCutoffPlane;
|
final Plane normalizedConnectingPlane, final double planeBoundingOffset) {
|
||||||
public final SidedPlane invertedEndCutoffPlane;
|
|
||||||
|
|
||||||
public PathSegment(final GeoPoint start, final GeoPoint end, final double planeBoundingOffset, final double arcWidth, final double chordDistance) {
|
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
|
this.normalizedConnectingPlane = normalizedConnectingPlane;
|
||||||
this.planeBoundingOffset = planeBoundingOffset;
|
this.planeBoundingOffset = planeBoundingOffset;
|
||||||
this.arcWidth = arcWidth;
|
|
||||||
this.chordDistance = chordDistance;
|
|
||||||
|
|
||||||
fullDistance = start.arcDistance(end);
|
fullDistance = start.arcDistance(end);
|
||||||
fullNormalDistance = start.normalDistance(end);
|
fullNormalDistance = start.normalDistance(end);
|
||||||
fullLinearDistance = start.linearDistance(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
|
// Either start or end should be on the correct side
|
||||||
upperConnectingPlane = new SidedPlane(start, normalizedConnectingPlane, -planeBoundingOffset);
|
upperConnectingPlane = new SidedPlane(start, normalizedConnectingPlane, -planeBoundingOffset);
|
||||||
lowerConnectingPlane = new SidedPlane(start, normalizedConnectingPlane, planeBoundingOffset);
|
lowerConnectingPlane = new SidedPlane(start, normalizedConnectingPlane, planeBoundingOffset);
|
||||||
|
@ -539,24 +618,40 @@ public class GeoPath extends GeoBaseExtendedShape implements GeoDistanceShape {
|
||||||
final Membership[] lowerSide = new Membership[]{lowerConnectingPlane};
|
final Membership[] lowerSide = new Membership[]{lowerConnectingPlane};
|
||||||
final Membership[] startSide = new Membership[]{startCutoffPlane};
|
final Membership[] startSide = new Membership[]{startCutoffPlane};
|
||||||
final Membership[] endSide = new Membership[]{endCutoffPlane};
|
final Membership[] endSide = new Membership[]{endCutoffPlane};
|
||||||
final GeoPoint ULHC = upperConnectingPlane.findIntersections(startCutoffPlane, lowerSide, endSide)[0];
|
GeoPoint[] points;
|
||||||
final GeoPoint URHC = upperConnectingPlane.findIntersections(endCutoffPlane, lowerSide, startSide)[0];
|
points = upperConnectingPlane.findIntersections(planetModel, startCutoffPlane, lowerSide, endSide);
|
||||||
final GeoPoint LLHC = lowerConnectingPlane.findIntersections(startCutoffPlane, upperSide, endSide)[0];
|
if (points.length == 0) {
|
||||||
final GeoPoint LRHC = lowerConnectingPlane.findIntersections(endCutoffPlane, upperSide, startSide)[0];
|
throw new IllegalArgumentException("Some segment boundary points are off the ellipsoid; path too wide");
|
||||||
|
}
|
||||||
|
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};
|
upperConnectingPlanePoints = new GeoPoint[]{ULHC, URHC};
|
||||||
lowerConnectingPlanePoints = new GeoPoint[]{LLHC, LRHC};
|
lowerConnectingPlanePoints = new GeoPoint[]{LLHC, LRHC};
|
||||||
startCutoffPlanePoints = new GeoPoint[]{ULHC, LLHC};
|
startCutoffPlanePoints = new GeoPoint[]{ULHC, LLHC};
|
||||||
endCutoffPlanePoints = new GeoPoint[]{URHC, LRHC};
|
endCutoffPlanePoints = new GeoPoint[]{URHC, LRHC};
|
||||||
invertedStartCutoffPlane = new SidedPlane(startCutoffPlane);
|
|
||||||
invertedEndCutoffPlane = new SidedPlane(endCutoffPlane);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDegenerate() {
|
|
||||||
return normalizedConnectingPlane == null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWithin(final Vector point) {
|
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) &&
|
return startCutoffPlane.isWithin(point) &&
|
||||||
endCutoffPlane.isWithin(point) &&
|
endCutoffPlane.isWithin(point) &&
|
||||||
upperConnectingPlane.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);
|
return point.linearDistance(normLineX, normLineY, normLineZ) + start.linearDistance(normLineX, normLineY, normLineZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
|
public boolean intersects(final PlanetModel planetModel, final Plane p, final GeoPoint[] notablePoints, final Membership[] bounds) {
|
||||||
return upperConnectingPlane.intersects(p, notablePoints, upperConnectingPlanePoints, bounds, lowerConnectingPlane, startCutoffPlane, endCutoffPlane) ||
|
return upperConnectingPlane.intersects(planetModel, p, notablePoints, upperConnectingPlanePoints, bounds, lowerConnectingPlane, startCutoffPlane, endCutoffPlane) ||
|
||||||
lowerConnectingPlane.intersects(p, notablePoints, lowerConnectingPlanePoints, bounds, upperConnectingPlane, 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
|
// We need to do all bounding planes as well as corner points
|
||||||
bounds.addPoint(start).addPoint(end);
|
bounds.addPoint(start).addPoint(end);
|
||||||
upperConnectingPlane.recordBounds(startCutoffPlane, bounds, lowerConnectingPlane, endCutoffPlane);
|
upperConnectingPlane.recordBounds(planetModel, startCutoffPlane, bounds, lowerConnectingPlane, endCutoffPlane);
|
||||||
startCutoffPlane.recordBounds(lowerConnectingPlane, bounds, endCutoffPlane, upperConnectingPlane);
|
startCutoffPlane.recordBounds(planetModel, lowerConnectingPlane, bounds, endCutoffPlane, upperConnectingPlane);
|
||||||
lowerConnectingPlane.recordBounds(endCutoffPlane, bounds, upperConnectingPlane, startCutoffPlane);
|
lowerConnectingPlane.recordBounds(planetModel, endCutoffPlane, bounds, upperConnectingPlane, startCutoffPlane);
|
||||||
endCutoffPlane.recordBounds(upperConnectingPlane, bounds, startCutoffPlane, lowerConnectingPlane);
|
endCutoffPlane.recordBounds(planetModel, upperConnectingPlane, bounds, startCutoffPlane, lowerConnectingPlane);
|
||||||
upperConnectingPlane.recordBounds(bounds, lowerConnectingPlane, startCutoffPlane, endCutoffPlane);
|
upperConnectingPlane.recordBounds(planetModel, bounds, lowerConnectingPlane, startCutoffPlane, endCutoffPlane);
|
||||||
lowerConnectingPlane.recordBounds(bounds, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
|
lowerConnectingPlane.recordBounds(planetModel, bounds, upperConnectingPlane, startCutoffPlane, endCutoffPlane);
|
||||||
startCutoffPlane.recordBounds(bounds, endCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
|
startCutoffPlane.recordBounds(planetModel, bounds, endCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
|
||||||
endCutoffPlane.recordBounds(bounds, startCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
|
endCutoffPlane.recordBounds(planetModel, bounds, startCutoffPlane, upperConnectingPlane, lowerConnectingPlane);
|
||||||
if (fullDistance >= Math.PI) {
|
if (fullDistance >= Math.PI) {
|
||||||
// Too large a segment basically means that we can confuse the Bounds object. Specifically, if our span exceeds 180 degrees
|
// 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).
|
// in longitude (which even a segment whose actual length is less than that might if it goes close to a pole).
|
||||||
|
|
|
@ -23,20 +23,85 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
||||||
* @lucene.experimental
|
* @lucene.experimental
|
||||||
*/
|
*/
|
||||||
public class GeoPoint extends Vector {
|
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);
|
/** This is the lazily-evaluated magnitude. Some constructors include it, but others don't, and
|
||||||
|
* we try not to create extra computation by always computing it. */
|
||||||
|
protected double magnitude = Double.NEGATIVE_INFINITY;
|
||||||
|
|
||||||
|
/** Construct a GeoPoint from the trig functions of a lat and lon pair.
|
||||||
|
* @param planetModel is the planetModel to put the point on.
|
||||||
|
* @param sinLat is the sin of the latitude.
|
||||||
|
* @param sinLon is the sin of the longitude.
|
||||||
|
* @param cosLat is the cos of the latitude.
|
||||||
|
* @param cosLon is the cos of the longitude.
|
||||||
|
*/
|
||||||
|
public GeoPoint(final PlanetModel planetModel, final double sinLat, final double sinLon, final double cosLat, final double cosLon) {
|
||||||
|
this(computeDesiredEllipsoidMagnitude(planetModel, cosLat * cosLon, cosLat * sinLon, sinLat),
|
||||||
|
cosLat * cosLon, cosLat * sinLon, sinLat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeoPoint(final double lat, final double lon) {
|
/** Construct a GeoPoint from a latitude/longitude pair.
|
||||||
this(Math.sin(lat), Math.sin(lon), Math.cos(lat), Math.cos(lon));
|
* @param planetModel is the planetModel to put the point on.
|
||||||
|
* @param lat is the latitude.
|
||||||
|
* @param lon is the longitude.
|
||||||
|
*/
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Construct a GeoPoint from a unit (x,y,z) vector and a magnitude.
|
||||||
|
* @param magnitude is the desired magnitude, provided to put the point on the ellipsoid.
|
||||||
|
* @param x is the unit x value.
|
||||||
|
* @param y is the unit y value.
|
||||||
|
* @param z is the unit z value.
|
||||||
|
*/
|
||||||
|
public GeoPoint(final double magnitude, final double x, final double y, final double z) {
|
||||||
|
super(x * magnitude, y * magnitude, z * magnitude);
|
||||||
|
this.magnitude = magnitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Construct a GeoPoint from an (x,y,z) value.
|
||||||
|
* The (x,y,z) tuple must be on the desired ellipsoid.
|
||||||
|
* @param x is the ellipsoid point x value.
|
||||||
|
* @param y is the ellipsoid point y value.
|
||||||
|
* @param z is the ellipsoid point z value.
|
||||||
|
*/
|
||||||
public GeoPoint(final double x, final double y, final double z) {
|
public GeoPoint(final double x, final double y, final double z) {
|
||||||
super(x, y, z);
|
super(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Compute an arc distance between two points.
|
||||||
|
* @param v is the second point.
|
||||||
|
* @return the angle, in radians, between the two points.
|
||||||
|
*/
|
||||||
public double arcDistance(final GeoPoint v) {
|
public double arcDistance(final GeoPoint v) {
|
||||||
return Tools.safeAcos(dotProduct(v));
|
return Tools.safeAcos(dotProduct(v)/(magnitude() * v.magnitude()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Compute the latitude for the point.
|
||||||
|
*@return the latitude.
|
||||||
|
*/
|
||||||
|
public double getLatitude() {
|
||||||
|
return Math.asin(z / magnitude() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Compute the longitude for the point.
|
||||||
|
* @return the longitude value. Uses 0.0 if there is no computable longitude.
|
||||||
|
*/
|
||||||
|
public double getLongitude() {
|
||||||
|
if (Math.abs(x) < MINIMUM_RESOLUTION && Math.abs(y) < MINIMUM_RESOLUTION)
|
||||||
|
return 0.0;
|
||||||
|
return Math.atan2(y,x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Compute the linear magnitude of the point.
|
||||||
|
* @return the 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.
|
* its neighbors determines inside/outside for the entire polygon.
|
||||||
* @return a GeoMembershipShape corresponding to what was specified.
|
* @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
|
// The basic operation uses a set of points, two points determining one particular edge, and a sided plane
|
||||||
// describing membership.
|
// 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())),
|
new SidedPlane(pointList.get(getLegalIndex(convexPointIndex - 1, pointList.size())),
|
||||||
pointList.get(convexPointIndex), pointList.get(getLegalIndex(convexPointIndex + 1, pointList.size()))),
|
pointList.get(convexPointIndex), pointList.get(getLegalIndex(convexPointIndex + 1, pointList.size()))),
|
||||||
false);
|
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:
|
// 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.
|
// 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.
|
// 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
|
// We want the other side for the recursion
|
||||||
SidedPlane otherSideNewBoundary = new SidedPlane(newBoundary);
|
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();
|
recursionList.clear();
|
||||||
}
|
}
|
||||||
currentList.add(newPoint);
|
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));
|
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
|
// We want the other side for the recursion
|
||||||
SidedPlane otherSideNewBoundary = new SidedPlane(newBoundary);
|
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();
|
recursionList.clear();
|
||||||
}
|
}
|
||||||
// Now, add in the current shape.
|
// 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");
|
//System.out.println("Done creating polygon");
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
||||||
*
|
*
|
||||||
* @lucene.internal
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoRectangle extends GeoBBoxBase {
|
public class GeoRectangle extends GeoBaseBBox {
|
||||||
public final double topLat;
|
public final double topLat;
|
||||||
public final double bottomLat;
|
public final double bottomLat;
|
||||||
public final double leftLon;
|
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}
|
* 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
|
// Argument checking
|
||||||
if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
|
if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
|
||||||
throw new IllegalArgumentException("Top latitude out of range");
|
throw new IllegalArgumentException("Top latitude out of range");
|
||||||
|
@ -88,10 +89,10 @@ public class GeoRectangle extends GeoBBoxBase {
|
||||||
final double cosRightLon = Math.cos(rightLon);
|
final double cosRightLon = Math.cos(rightLon);
|
||||||
|
|
||||||
// Now build the four points
|
// Now build the four points
|
||||||
this.ULHC = new GeoPoint(sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
|
this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
|
||||||
this.URHC = new GeoPoint(sinTopLat, sinRightLon, cosTopLat, cosRightLon);
|
this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon);
|
||||||
this.LRHC = new GeoPoint(sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
|
this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
|
||||||
this.LLHC = new GeoPoint(sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
|
this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
|
||||||
|
|
||||||
final double middleLat = (topLat + bottomLat) * 0.5;
|
final double middleLat = (topLat + bottomLat) * 0.5;
|
||||||
final double sinMiddleLat = Math.sin(middleLat);
|
final double sinMiddleLat = Math.sin(middleLat);
|
||||||
|
@ -104,10 +105,10 @@ public class GeoRectangle extends GeoBBoxBase {
|
||||||
final double sinMiddleLon = Math.sin(middleLon);
|
final double sinMiddleLon = Math.sin(middleLon);
|
||||||
final double cosMiddleLon = Math.cos(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.bottomPlane = new SidedPlane(centerPoint, sinBottomLat);
|
this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
|
||||||
this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||||
|
|
||||||
|
@ -133,7 +134,7 @@ public class GeoRectangle extends GeoBBoxBase {
|
||||||
newLeftLon = -Math.PI;
|
newLeftLon = -Math.PI;
|
||||||
newRightLon = Math.PI;
|
newRightLon = Math.PI;
|
||||||
}
|
}
|
||||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -180,10 +181,10 @@ public class GeoRectangle extends GeoBBoxBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||||
return p.intersects(topPlane, notablePoints, topPlanePoints, bounds, bottomPlane, leftPlane, rightPlane) ||
|
return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, bottomPlane, leftPlane, rightPlane) ||
|
||||||
p.intersects(bottomPlane, notablePoints, bottomPlanePoints, bounds, topPlane, leftPlane, rightPlane) ||
|
p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, topPlane, leftPlane, rightPlane) ||
|
||||||
p.intersects(leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, topPlane, bottomPlane) ||
|
p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, topPlane, bottomPlane) ||
|
||||||
p.intersects(rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, 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))
|
if (!(o instanceof GeoRectangle))
|
||||||
return false;
|
return false;
|
||||||
GeoRectangle other = (GeoRectangle) o;
|
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = ULHC.hashCode();
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + ULHC.hashCode();
|
||||||
result = 31 * result + LRHC.hashCode();
|
result = 31 * result + LRHC.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoSouthLatitudeZone extends GeoBBoxBase {
|
public class GeoSouthLatitudeZone extends GeoBaseBBox {
|
||||||
public final double topLat;
|
public final double topLat;
|
||||||
public final double cosTopLat;
|
public final double cosTopLat;
|
||||||
public final SidedPlane topPlane;
|
public final SidedPlane topPlane;
|
||||||
|
@ -34,22 +34,20 @@ public class GeoSouthLatitudeZone extends GeoBBoxBase {
|
||||||
// Edge points
|
// Edge points
|
||||||
public final GeoPoint[] edgePoints;
|
public final GeoPoint[] edgePoints;
|
||||||
|
|
||||||
public GeoSouthLatitudeZone(final double topLat) {
|
public GeoSouthLatitudeZone(final PlanetModel planetModel, final double topLat) {
|
||||||
|
super(planetModel);
|
||||||
this.topLat = topLat;
|
this.topLat = topLat;
|
||||||
|
|
||||||
final double sinTopLat = Math.sin(topLat);
|
final double sinTopLat = Math.sin(topLat);
|
||||||
this.cosTopLat = Math.cos(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.
|
// 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 middleLat = (topLat - Math.PI * 0.5) * 0.5;
|
||||||
final double sinMiddleLat = Math.sin(middleLat);
|
final double sinMiddleLat = Math.sin(middleLat);
|
||||||
this.interiorPoint = new GeoPoint(Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 0.0, sinMiddleLat);
|
this.interiorPoint = new GeoPoint(planetModel, sinMiddleLat, 0.0, Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 1.0);
|
||||||
this.topBoundaryPoint = new GeoPoint(Math.sqrt(1.0 - sinTopLat * sinTopLat), 0.0, sinTopLat);
|
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};
|
this.edgePoints = new GeoPoint[]{topBoundaryPoint};
|
||||||
}
|
}
|
||||||
|
@ -58,7 +56,7 @@ public class GeoSouthLatitudeZone extends GeoBBoxBase {
|
||||||
public GeoBBox expand(final double angle) {
|
public GeoBBox expand(final double angle) {
|
||||||
final double newTopLat = topLat + angle;
|
final double newTopLat = topLat + angle;
|
||||||
final double newBottomLat = -Math.PI * 0.5;
|
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
|
@Override
|
||||||
|
@ -98,7 +96,7 @@ public class GeoSouthLatitudeZone extends GeoBBoxBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
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))
|
if (!(o instanceof GeoSouthLatitudeZone))
|
||||||
return false;
|
return false;
|
||||||
GeoSouthLatitudeZone other = (GeoSouthLatitudeZone) o;
|
GeoSouthLatitudeZone other = (GeoSouthLatitudeZone) o;
|
||||||
return other.topPlane.equals(topPlane);
|
return super.equals(other) && other.topBoundaryPoint.equals(topBoundaryPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = topPlane.hashCode();
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + topBoundaryPoint.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoSouthRectangle extends GeoBBoxBase {
|
public class GeoSouthRectangle extends GeoBaseBBox {
|
||||||
public final double topLat;
|
public final double topLat;
|
||||||
public final double leftLon;
|
public final double leftLon;
|
||||||
public final double rightLon;
|
public final double rightLon;
|
||||||
|
@ -45,12 +45,13 @@ public class GeoSouthRectangle extends GeoBBoxBase {
|
||||||
|
|
||||||
public final GeoPoint centerPoint;
|
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}
|
* 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
|
// Argument checking
|
||||||
if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
|
if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
|
||||||
throw new IllegalArgumentException("Top latitude out of range");
|
throw new IllegalArgumentException("Top latitude out of range");
|
||||||
|
@ -77,8 +78,8 @@ public class GeoSouthRectangle extends GeoBBoxBase {
|
||||||
final double cosRightLon = Math.cos(rightLon);
|
final double cosRightLon = Math.cos(rightLon);
|
||||||
|
|
||||||
// Now build the four points
|
// Now build the four points
|
||||||
this.ULHC = new GeoPoint(sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
|
this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
|
||||||
this.URHC = new GeoPoint(sinTopLat, sinRightLon, cosTopLat, cosRightLon);
|
this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon);
|
||||||
|
|
||||||
final double middleLat = (topLat - Math.PI * 0.5) * 0.5;
|
final double middleLat = (topLat - Math.PI * 0.5) * 0.5;
|
||||||
final double sinMiddleLat = Math.sin(middleLat);
|
final double sinMiddleLat = Math.sin(middleLat);
|
||||||
|
@ -91,15 +92,18 @@ public class GeoSouthRectangle extends GeoBBoxBase {
|
||||||
final double sinMiddleLon = Math.sin(middleLon);
|
final double sinMiddleLon = Math.sin(middleLon);
|
||||||
final double cosMiddleLon = Math.cos(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.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||||
|
|
||||||
this.topPlanePoints = new GeoPoint[]{ULHC, URHC};
|
this.topPlanePoints = new GeoPoint[]{ULHC, URHC};
|
||||||
this.leftPlanePoints = new GeoPoint[]{ULHC, SOUTH_POLE};
|
this.leftPlanePoints = new GeoPoint[]{ULHC, planetModel.SOUTH_POLE};
|
||||||
this.rightPlanePoints = new GeoPoint[]{URHC, SOUTH_POLE};
|
this.rightPlanePoints = new GeoPoint[]{URHC, planetModel.SOUTH_POLE};
|
||||||
|
|
||||||
|
this.edgePoints = new GeoPoint[]{planetModel.SOUTH_POLE};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -116,7 +120,7 @@ public class GeoSouthRectangle extends GeoBBoxBase {
|
||||||
newLeftLon = -Math.PI;
|
newLeftLon = -Math.PI;
|
||||||
newRightLon = Math.PI;
|
newRightLon = Math.PI;
|
||||||
}
|
}
|
||||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -160,9 +164,9 @@ public class GeoSouthRectangle extends GeoBBoxBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||||
return p.intersects(topPlane, notablePoints, topPlanePoints, bounds, leftPlane, rightPlane) ||
|
return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, leftPlane, rightPlane) ||
|
||||||
p.intersects(leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, topPlane) ||
|
p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, rightPlane, topPlane) ||
|
||||||
p.intersects(rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, topPlane);
|
p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, leftPlane, topPlane);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -192,7 +196,7 @@ public class GeoSouthRectangle extends GeoBBoxBase {
|
||||||
return OVERLAPS;
|
return OVERLAPS;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean insideShape = path.isWithin(SOUTH_POLE);
|
final boolean insideShape = path.isWithin(planetModel.SOUTH_POLE);
|
||||||
|
|
||||||
if (insideRectangle == ALL_INSIDE && insideShape) {
|
if (insideRectangle == ALL_INSIDE && insideShape) {
|
||||||
//System.err.println(" inside of each other");
|
//System.err.println(" inside of each other");
|
||||||
|
@ -224,19 +228,20 @@ public class GeoSouthRectangle extends GeoBBoxBase {
|
||||||
if (!(o instanceof GeoSouthRectangle))
|
if (!(o instanceof GeoSouthRectangle))
|
||||||
return false;
|
return false;
|
||||||
GeoSouthRectangle other = (GeoSouthRectangle) o;
|
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = ULHC.hashCode();
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + ULHC.hashCode();
|
||||||
result = 31 * result + URHC.hashCode();
|
result = 31 * result + URHC.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoWideDegenerateHorizontalLine extends GeoBBoxBase {
|
public class GeoWideDegenerateHorizontalLine extends GeoBaseBBox {
|
||||||
public final double latitude;
|
public final double latitude;
|
||||||
public final double leftLon;
|
public final double leftLon;
|
||||||
public final double rightLon;
|
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}.
|
* 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.
|
* 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
|
// Argument checking
|
||||||
if (latitude > Math.PI * 0.5 || latitude < -Math.PI * 0.5)
|
if (latitude > Math.PI * 0.5 || latitude < -Math.PI * 0.5)
|
||||||
throw new IllegalArgumentException("Latitude out of range");
|
throw new IllegalArgumentException("Latitude out of range");
|
||||||
|
@ -73,10 +74,10 @@ public class GeoWideDegenerateHorizontalLine extends GeoBBoxBase {
|
||||||
final double cosRightLon = Math.cos(rightLon);
|
final double cosRightLon = Math.cos(rightLon);
|
||||||
|
|
||||||
// Now build the two points
|
// Now build the two points
|
||||||
this.LHC = new GeoPoint(sinLatitude, sinLeftLon, cosLatitude, cosLeftLon);
|
this.LHC = new GeoPoint(planetModel, sinLatitude, sinLeftLon, cosLatitude, cosLeftLon);
|
||||||
this.RHC = new GeoPoint(sinLatitude, sinRightLon, cosLatitude, cosRightLon);
|
this.RHC = new GeoPoint(planetModel, sinLatitude, sinRightLon, cosLatitude, cosRightLon);
|
||||||
|
|
||||||
this.plane = new Plane(sinLatitude);
|
this.plane = new Plane(planetModel, sinLatitude);
|
||||||
|
|
||||||
// Normalize
|
// Normalize
|
||||||
while (leftLon > rightLon) {
|
while (leftLon > rightLon) {
|
||||||
|
@ -86,7 +87,7 @@ public class GeoWideDegenerateHorizontalLine extends GeoBBoxBase {
|
||||||
double sinMiddleLon = Math.sin(middleLon);
|
double sinMiddleLon = Math.sin(middleLon);
|
||||||
double cosMiddleLon = Math.cos(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.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||||
|
@ -112,7 +113,7 @@ public class GeoWideDegenerateHorizontalLine extends GeoBBoxBase {
|
||||||
newLeftLon = -Math.PI;
|
newLeftLon = -Math.PI;
|
||||||
newRightLon = Math.PI;
|
newRightLon = Math.PI;
|
||||||
}
|
}
|
||||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -160,7 +161,7 @@ public class GeoWideDegenerateHorizontalLine extends GeoBBoxBase {
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||||
// Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
|
// 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.
|
// 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))
|
if (!(o instanceof GeoWideDegenerateHorizontalLine))
|
||||||
return false;
|
return false;
|
||||||
GeoWideDegenerateHorizontalLine other = (GeoWideDegenerateHorizontalLine) o;
|
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = LHC.hashCode();
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + LHC.hashCode();
|
||||||
result = 31 * result + RHC.hashCode();
|
result = 31 * result + RHC.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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 {
|
protected class EitherBound implements Membership {
|
||||||
|
|
|
@ -23,24 +23,25 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
||||||
*
|
*
|
||||||
* @lucene.internal
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoWideLongitudeSlice extends GeoBBoxBase {
|
public class GeoWideLongitudeSlice extends GeoBaseBBox {
|
||||||
public final double leftLon;
|
public final double leftLon;
|
||||||
public final double rightLon;
|
public final double rightLon;
|
||||||
|
|
||||||
public final SidedPlane leftPlane;
|
public final SidedPlane leftPlane;
|
||||||
public final SidedPlane rightPlane;
|
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 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}.
|
* Accepts only values in the following ranges: lon: {@code -PI -> PI}.
|
||||||
* Horizantal angle must be greater than or equal to 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
|
// Argument checking
|
||||||
if (leftLon < -Math.PI || leftLon > Math.PI)
|
if (leftLon < -Math.PI || leftLon > Math.PI)
|
||||||
throw new IllegalArgumentException("Left longitude out of range");
|
throw new IllegalArgumentException("Left longitude out of range");
|
||||||
|
@ -66,10 +67,13 @@ public class GeoWideLongitudeSlice extends GeoBBoxBase {
|
||||||
rightLon += Math.PI * 2.0;
|
rightLon += Math.PI * 2.0;
|
||||||
}
|
}
|
||||||
final double middleLon = (leftLon + rightLon) * 0.5;
|
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.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
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
|
@Override
|
||||||
|
@ -84,7 +88,7 @@ public class GeoWideLongitudeSlice extends GeoBBoxBase {
|
||||||
newLeftLon = -Math.PI;
|
newLeftLon = -Math.PI;
|
||||||
newRightLon = 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
|
@Override
|
||||||
|
@ -127,8 +131,8 @@ public class GeoWideLongitudeSlice extends GeoBBoxBase {
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||||
// Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
|
// 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.
|
// requires crossing into the right part of the other. So intersection can ignore the left/right bounds.
|
||||||
return p.intersects(leftPlane, notablePoints, planePoints, bounds) ||
|
return p.intersects(planetModel, leftPlane, notablePoints, planePoints, bounds) ||
|
||||||
p.intersects(rightPlane, notablePoints, planePoints, bounds);
|
p.intersects(planetModel, rightPlane, notablePoints, planePoints, bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -155,7 +159,7 @@ public class GeoWideLongitudeSlice extends GeoBBoxBase {
|
||||||
if (insideRectangle == SOME_INSIDE)
|
if (insideRectangle == SOME_INSIDE)
|
||||||
return OVERLAPS;
|
return OVERLAPS;
|
||||||
|
|
||||||
final boolean insideShape = path.isWithin(NORTH_POLE);
|
final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
|
||||||
|
|
||||||
if (insideRectangle == ALL_INSIDE && insideShape)
|
if (insideRectangle == ALL_INSIDE && insideShape)
|
||||||
return OVERLAPS;
|
return OVERLAPS;
|
||||||
|
@ -178,15 +182,14 @@ public class GeoWideLongitudeSlice extends GeoBBoxBase {
|
||||||
if (!(o instanceof GeoWideLongitudeSlice))
|
if (!(o instanceof GeoWideLongitudeSlice))
|
||||||
return false;
|
return false;
|
||||||
GeoWideLongitudeSlice other = (GeoWideLongitudeSlice) o;
|
GeoWideLongitudeSlice other = (GeoWideLongitudeSlice) o;
|
||||||
return other.leftLon == leftLon && other.rightLon == rightLon;
|
return super.equals(other) && other.leftLon == leftLon && other.rightLon == rightLon;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result;
|
int result = super.hashCode();
|
||||||
long temp;
|
long temp = Double.doubleToLongBits(leftLon);
|
||||||
temp = Double.doubleToLongBits(leftLon);
|
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||||
result = (int) (temp ^ (temp >>> 32));
|
|
||||||
temp = Double.doubleToLongBits(rightLon);
|
temp = Double.doubleToLongBits(rightLon);
|
||||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||||
return result;
|
return result;
|
||||||
|
@ -194,7 +197,7 @@ public class GeoWideLongitudeSlice extends GeoBBoxBase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoWideNorthRectangle extends GeoBBoxBase {
|
public class GeoWideNorthRectangle extends GeoBaseBBox {
|
||||||
public final double bottomLat;
|
public final double bottomLat;
|
||||||
public final double leftLon;
|
public final double leftLon;
|
||||||
public final double rightLon;
|
public final double rightLon;
|
||||||
|
@ -45,13 +45,14 @@ public class GeoWideNorthRectangle extends GeoBBoxBase {
|
||||||
|
|
||||||
public final EitherBound eitherBound;
|
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}.
|
* 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.
|
* 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
|
// Argument checking
|
||||||
if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
|
if (bottomLat > Math.PI * 0.5 || bottomLat < -Math.PI * 0.5)
|
||||||
throw new IllegalArgumentException("Bottom latitude out of range");
|
throw new IllegalArgumentException("Bottom latitude out of range");
|
||||||
|
@ -78,8 +79,8 @@ public class GeoWideNorthRectangle extends GeoBBoxBase {
|
||||||
final double cosRightLon = Math.cos(rightLon);
|
final double cosRightLon = Math.cos(rightLon);
|
||||||
|
|
||||||
// Now build the four points
|
// Now build the four points
|
||||||
this.LRHC = new GeoPoint(sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
|
this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
|
||||||
this.LLHC = new GeoPoint(sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
|
this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
|
||||||
|
|
||||||
final double middleLat = (Math.PI * 0.5 + bottomLat) * 0.5;
|
final double middleLat = (Math.PI * 0.5 + bottomLat) * 0.5;
|
||||||
final double sinMiddleLat = Math.sin(middleLat);
|
final double sinMiddleLat = Math.sin(middleLat);
|
||||||
|
@ -92,17 +93,18 @@ public class GeoWideNorthRectangle extends GeoBBoxBase {
|
||||||
final double sinMiddleLon = Math.sin(middleLon);
|
final double sinMiddleLon = Math.sin(middleLon);
|
||||||
final double cosMiddleLon = Math.cos(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.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||||
|
|
||||||
this.bottomPlanePoints = new GeoPoint[]{LLHC, LRHC};
|
this.bottomPlanePoints = new GeoPoint[]{LLHC, LRHC};
|
||||||
this.leftPlanePoints = new GeoPoint[]{NORTH_POLE, LLHC};
|
this.leftPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LLHC};
|
||||||
this.rightPlanePoints = new GeoPoint[]{NORTH_POLE, LRHC};
|
this.rightPlanePoints = new GeoPoint[]{planetModel.NORTH_POLE, LRHC};
|
||||||
|
|
||||||
this.eitherBound = new EitherBound();
|
this.eitherBound = new EitherBound();
|
||||||
|
this.edgePoints = new GeoPoint[]{planetModel.NORTH_POLE};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -119,7 +121,7 @@ public class GeoWideNorthRectangle extends GeoBBoxBase {
|
||||||
newLeftLon = -Math.PI;
|
newLeftLon = -Math.PI;
|
||||||
newRightLon = Math.PI;
|
newRightLon = Math.PI;
|
||||||
}
|
}
|
||||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
// 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.
|
// requires crossing into the right part of the other. So intersection can ignore the left/right bounds.
|
||||||
return
|
return
|
||||||
p.intersects(bottomPlane, notablePoints, bottomPlanePoints, bounds, eitherBound) ||
|
p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, eitherBound) ||
|
||||||
p.intersects(leftPlane, notablePoints, leftPlanePoints, bounds, bottomPlane) ||
|
p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, bottomPlane) ||
|
||||||
p.intersects(rightPlane, notablePoints, rightPlanePoints, bounds, bottomPlane);
|
p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, bottomPlane);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -200,7 +202,7 @@ public class GeoWideNorthRectangle extends GeoBBoxBase {
|
||||||
return OVERLAPS;
|
return OVERLAPS;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean insideShape = path.isWithin(NORTH_POLE);
|
final boolean insideShape = path.isWithin(planetModel.NORTH_POLE);
|
||||||
|
|
||||||
if (insideRectangle == ALL_INSIDE && insideShape) {
|
if (insideRectangle == ALL_INSIDE && insideShape) {
|
||||||
//System.err.println(" both inside each other");
|
//System.err.println(" both inside each other");
|
||||||
|
@ -234,19 +236,20 @@ public class GeoWideNorthRectangle extends GeoBBoxBase {
|
||||||
if (!(o instanceof GeoWideNorthRectangle))
|
if (!(o instanceof GeoWideNorthRectangle))
|
||||||
return false;
|
return false;
|
||||||
GeoWideNorthRectangle other = (GeoWideNorthRectangle) o;
|
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = LLHC.hashCode();
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + LLHC.hashCode();
|
||||||
result = 31 * result + LRHC.hashCode();
|
result = 31 * result + LRHC.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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 {
|
protected class EitherBound implements Membership {
|
||||||
|
|
|
@ -23,7 +23,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
||||||
*
|
*
|
||||||
* @lucene.internal
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoWideRectangle extends GeoBBoxBase {
|
public class GeoWideRectangle extends GeoBaseBBox {
|
||||||
public final double topLat;
|
public final double topLat;
|
||||||
public final double bottomLat;
|
public final double bottomLat;
|
||||||
public final double leftLon;
|
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}.
|
* 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.
|
* 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
|
// Argument checking
|
||||||
if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
|
if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
|
||||||
throw new IllegalArgumentException("Top latitude out of range");
|
throw new IllegalArgumentException("Top latitude out of range");
|
||||||
|
@ -90,10 +91,10 @@ public class GeoWideRectangle extends GeoBBoxBase {
|
||||||
final double cosRightLon = Math.cos(rightLon);
|
final double cosRightLon = Math.cos(rightLon);
|
||||||
|
|
||||||
// Now build the four points
|
// Now build the four points
|
||||||
this.ULHC = new GeoPoint(sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
|
this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
|
||||||
this.URHC = new GeoPoint(sinTopLat, sinRightLon, cosTopLat, cosRightLon);
|
this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon);
|
||||||
this.LRHC = new GeoPoint(sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
|
this.LRHC = new GeoPoint(planetModel, sinBottomLat, sinRightLon, cosBottomLat, cosRightLon);
|
||||||
this.LLHC = new GeoPoint(sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
|
this.LLHC = new GeoPoint(planetModel, sinBottomLat, sinLeftLon, cosBottomLat, cosLeftLon);
|
||||||
|
|
||||||
final double middleLat = (topLat + bottomLat) * 0.5;
|
final double middleLat = (topLat + bottomLat) * 0.5;
|
||||||
final double sinMiddleLat = Math.sin(middleLat);
|
final double sinMiddleLat = Math.sin(middleLat);
|
||||||
|
@ -106,10 +107,10 @@ public class GeoWideRectangle extends GeoBBoxBase {
|
||||||
final double sinMiddleLon = Math.sin(middleLon);
|
final double sinMiddleLon = Math.sin(middleLon);
|
||||||
final double cosMiddleLon = Math.cos(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.bottomPlane = new SidedPlane(centerPoint, sinBottomLat);
|
this.bottomPlane = new SidedPlane(centerPoint, planetModel, sinBottomLat);
|
||||||
this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
this.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||||
|
|
||||||
|
@ -137,7 +138,7 @@ public class GeoWideRectangle extends GeoBBoxBase {
|
||||||
newLeftLon = -Math.PI;
|
newLeftLon = -Math.PI;
|
||||||
newRightLon = Math.PI;
|
newRightLon = Math.PI;
|
||||||
}
|
}
|
||||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -186,10 +187,10 @@ public class GeoWideRectangle extends GeoBBoxBase {
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||||
// Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
|
// 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.
|
// 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) ||
|
return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, bottomPlane, eitherBound) ||
|
||||||
p.intersects(bottomPlane, notablePoints, bottomPlanePoints, bounds, topPlane, eitherBound) ||
|
p.intersects(planetModel, bottomPlane, notablePoints, bottomPlanePoints, bounds, topPlane, eitherBound) ||
|
||||||
p.intersects(leftPlane, notablePoints, leftPlanePoints, bounds, topPlane, bottomPlane) ||
|
p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, topPlane, bottomPlane) ||
|
||||||
p.intersects(rightPlane, notablePoints, rightPlanePoints, 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))
|
if (!(o instanceof GeoWideRectangle))
|
||||||
return false;
|
return false;
|
||||||
GeoWideRectangle other = (GeoWideRectangle) o;
|
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = ULHC.hashCode();
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + ULHC.hashCode();
|
||||||
result = 31 * result + LRHC.hashCode();
|
result = 31 * result + LRHC.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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 {
|
protected class EitherBound implements Membership {
|
||||||
|
|
|
@ -23,7 +23,7 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
||||||
*
|
*
|
||||||
* @lucene.internal
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoWideSouthRectangle extends GeoBBoxBase {
|
public class GeoWideSouthRectangle extends GeoBaseBBox {
|
||||||
public final double topLat;
|
public final double topLat;
|
||||||
public final double leftLon;
|
public final double leftLon;
|
||||||
public final double rightLon;
|
public final double rightLon;
|
||||||
|
@ -45,13 +45,14 @@ public class GeoWideSouthRectangle extends GeoBBoxBase {
|
||||||
|
|
||||||
public final EitherBound eitherBound;
|
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}.
|
* 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.
|
* 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
|
// Argument checking
|
||||||
if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
|
if (topLat > Math.PI * 0.5 || topLat < -Math.PI * 0.5)
|
||||||
throw new IllegalArgumentException("Top latitude out of range");
|
throw new IllegalArgumentException("Top latitude out of range");
|
||||||
|
@ -78,8 +79,8 @@ public class GeoWideSouthRectangle extends GeoBBoxBase {
|
||||||
final double cosRightLon = Math.cos(rightLon);
|
final double cosRightLon = Math.cos(rightLon);
|
||||||
|
|
||||||
// Now build the four points
|
// Now build the four points
|
||||||
this.ULHC = new GeoPoint(sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
|
this.ULHC = new GeoPoint(planetModel, sinTopLat, sinLeftLon, cosTopLat, cosLeftLon);
|
||||||
this.URHC = new GeoPoint(sinTopLat, sinRightLon, cosTopLat, cosRightLon);
|
this.URHC = new GeoPoint(planetModel, sinTopLat, sinRightLon, cosTopLat, cosRightLon);
|
||||||
|
|
||||||
final double middleLat = (topLat - Math.PI * 0.5) * 0.5;
|
final double middleLat = (topLat - Math.PI * 0.5) * 0.5;
|
||||||
final double sinMiddleLat = Math.sin(middleLat);
|
final double sinMiddleLat = Math.sin(middleLat);
|
||||||
|
@ -92,17 +93,19 @@ public class GeoWideSouthRectangle extends GeoBBoxBase {
|
||||||
final double sinMiddleLon = Math.sin(middleLon);
|
final double sinMiddleLon = Math.sin(middleLon);
|
||||||
final double cosMiddleLon = Math.cos(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.leftPlane = new SidedPlane(centerPoint, cosLeftLon, sinLeftLon);
|
||||||
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
this.rightPlane = new SidedPlane(centerPoint, cosRightLon, sinRightLon);
|
||||||
|
|
||||||
this.topPlanePoints = new GeoPoint[]{ULHC, URHC};
|
this.topPlanePoints = new GeoPoint[]{ULHC, URHC};
|
||||||
this.leftPlanePoints = new GeoPoint[]{ULHC, SOUTH_POLE};
|
this.leftPlanePoints = new GeoPoint[]{ULHC, planetModel.SOUTH_POLE};
|
||||||
this.rightPlanePoints = new GeoPoint[]{URHC, SOUTH_POLE};
|
this.rightPlanePoints = new GeoPoint[]{URHC, planetModel.SOUTH_POLE};
|
||||||
|
|
||||||
this.eitherBound = new EitherBound();
|
this.eitherBound = new EitherBound();
|
||||||
|
|
||||||
|
this.edgePoints = new GeoPoint[]{planetModel.SOUTH_POLE};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -119,7 +122,7 @@ public class GeoWideSouthRectangle extends GeoBBoxBase {
|
||||||
newLeftLon = -Math.PI;
|
newLeftLon = -Math.PI;
|
||||||
newRightLon = Math.PI;
|
newRightLon = Math.PI;
|
||||||
}
|
}
|
||||||
return GeoBBoxFactory.makeGeoBBox(newTopLat, newBottomLat, newLeftLon, newRightLon);
|
return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, newLeftLon, newRightLon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -165,9 +168,9 @@ public class GeoWideSouthRectangle extends GeoBBoxBase {
|
||||||
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
|
||||||
// Right and left bounds are essentially independent hemispheres; crossing into the wrong part of one
|
// 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.
|
// 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) ||
|
return p.intersects(planetModel, topPlane, notablePoints, topPlanePoints, bounds, eitherBound) ||
|
||||||
p.intersects(leftPlane, notablePoints, leftPlanePoints, bounds, topPlane) ||
|
p.intersects(planetModel, leftPlane, notablePoints, leftPlanePoints, bounds, topPlane) ||
|
||||||
p.intersects(rightPlane, notablePoints, rightPlanePoints, bounds, topPlane);
|
p.intersects(planetModel, rightPlane, notablePoints, rightPlanePoints, bounds, topPlane);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -197,7 +200,7 @@ public class GeoWideSouthRectangle extends GeoBBoxBase {
|
||||||
return OVERLAPS;
|
return OVERLAPS;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean insideShape = path.isWithin(SOUTH_POLE);
|
final boolean insideShape = path.isWithin(planetModel.SOUTH_POLE);
|
||||||
|
|
||||||
if (insideRectangle == ALL_INSIDE && insideShape) {
|
if (insideRectangle == ALL_INSIDE && insideShape) {
|
||||||
//System.err.println(" both inside each other");
|
//System.err.println(" both inside each other");
|
||||||
|
@ -230,19 +233,20 @@ public class GeoWideSouthRectangle extends GeoBBoxBase {
|
||||||
if (!(o instanceof GeoWideSouthRectangle))
|
if (!(o instanceof GeoWideSouthRectangle))
|
||||||
return false;
|
return false;
|
||||||
GeoWideSouthRectangle other = (GeoWideSouthRectangle) o;
|
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int result = ULHC.hashCode();
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + ULHC.hashCode();
|
||||||
result = 31 * result + URHC.hashCode();
|
result = 31 * result + URHC.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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 {
|
protected class EitherBound implements Membership {
|
||||||
|
|
|
@ -22,11 +22,13 @@ package org.apache.lucene.spatial.spatial4j.geo3d;
|
||||||
*
|
*
|
||||||
* @lucene.internal
|
* @lucene.internal
|
||||||
*/
|
*/
|
||||||
public class GeoWorld extends GeoBBoxBase {
|
public class GeoWorld extends GeoBaseBBox {
|
||||||
protected final static GeoPoint originPoint = new GeoPoint(1.0, 0.0, 0.0);
|
|
||||||
protected final static GeoPoint[] edgePoints = new GeoPoint[0];
|
protected final static GeoPoint[] edgePoints = new GeoPoint[0];
|
||||||
|
protected final GeoPoint originPoint;
|
||||||
|
|
||||||
public GeoWorld() {
|
public GeoWorld(final PlanetModel planetModel) {
|
||||||
|
super(planetModel);
|
||||||
|
originPoint = new GeoPoint(planetModel.ab, 1.0, 0.0, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -100,16 +102,16 @@ public class GeoWorld extends GeoBBoxBase {
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (!(o instanceof GeoWorld))
|
if (!(o instanceof GeoWorld))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return super.equals(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return 0;
|
return super.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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.
|
* 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);
|
super(0.0, 0.0, 1.0);
|
||||||
D = -height;
|
D = -sinLat * computeDesiredEllipsoidMagnitude(planetModel, sinLat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,6 +82,15 @@ public class Plane extends Vector {
|
||||||
this.D = D;
|
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
|
* Evaluate the plane equation for a given point, as represented
|
||||||
* by a vector.
|
* by a vector.
|
||||||
|
@ -289,15 +299,27 @@ public class Plane extends Vector {
|
||||||
return new GeoPoint(result.x, result.y, result.z);
|
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.
|
* 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 q is the plane to intersect with.
|
||||||
* @param bounds is the set of bounds.
|
* @param bounds is the set of bounds.
|
||||||
* @param moreBounds is another set of bounds.
|
* @param moreBounds is another set of bounds.
|
||||||
* @return the intersection point(s) on the unit sphere, if there are any.
|
* @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);
|
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) {
|
if (Math.abs(lineVector.x) < MINIMUM_RESOLUTION && Math.abs(lineVector.y) < MINIMUM_RESOLUTION && Math.abs(lineVector.z) < MINIMUM_RESOLUTION) {
|
||||||
// Degenerate case: parallel planes
|
// Degenerate case: parallel planes
|
||||||
|
@ -363,16 +385,18 @@ public class Plane extends Vector {
|
||||||
z0 = 0.0;
|
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.
|
// 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:
|
// The ellipsoid equation: 1,0 = x^2/a^2 + y^2/b^2 + z^2/c^2
|
||||||
// 1.0 = (At+A0)^2 + (Bt+B0)^2 + (Ct+C0)^2
|
// 1.0 = (At+A0)^2/a^2 + (Bt+B0)^2/b^2 + (Ct+C0)^2/c^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 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 + B^2 + C^2] t^2 + [2AA0 + 2BB0 + 2CC0] t + [A0^2 + B0^2 + C0^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)
|
// 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 A = lineVector.x * lineVector.x * planetModel.inverseAbSquared +
|
||||||
final double B = 2.0 * (lineVector.x * x0 + lineVector.y * y0 + lineVector.z * z0);
|
lineVector.y * lineVector.y * planetModel.inverseAbSquared +
|
||||||
final double C = x0 * x0 + y0 * y0 + z0 * z0 - 1.0;
|
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;
|
final double BsquaredMinus = B * B - 4.0 * A * C;
|
||||||
if (Math.abs(BsquaredMinus) < MINIMUM_RESOLUTION_SQUARED) {
|
if (Math.abs(BsquaredMinus) < MINIMUM_RESOLUTION_SQUARED) {
|
||||||
|
@ -381,6 +405,8 @@ public class Plane extends Vector {
|
||||||
// One solution only
|
// One solution only
|
||||||
final double t = -B * inverse2A;
|
final double t = -B * inverse2A;
|
||||||
GeoPoint point = new GeoPoint(lineVector.x * t + x0, lineVector.y * t + y0, lineVector.z * t + z0);
|
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))
|
if (point.isWithin(bounds, moreBounds))
|
||||||
return new GeoPoint[]{point};
|
return new GeoPoint[]{point};
|
||||||
return NO_POINTS;
|
return NO_POINTS;
|
||||||
|
@ -393,6 +419,8 @@ public class Plane extends Vector {
|
||||||
final double t2 = (-B - sqrtTerm) * inverse2A;
|
final double t2 = (-B - sqrtTerm) * inverse2A;
|
||||||
GeoPoint point1 = new GeoPoint(lineVector.x * t1 + x0, lineVector.y * t1 + y0, lineVector.z * t1 + z0);
|
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);
|
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);
|
//System.err.println(" "+point1+" and "+point2);
|
||||||
if (point1.isWithin(bounds, moreBounds)) {
|
if (point1.isWithin(bounds, moreBounds)) {
|
||||||
if (point2.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
|
* Accumulate bounds information for this plane, intersected with another plane
|
||||||
* and with the unit sphere.
|
* and with the unit sphere.
|
||||||
* Updates both latitude and longitude information, using max/min points found
|
* Updates both latitude and longitude information, using max/min points found
|
||||||
* within the specified bounds.
|
* 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 q is the plane to intersect with.
|
||||||
* @param boundsInfo is the info to update with additional bounding information.
|
* @param boundsInfo is the info to update with additional bounding information.
|
||||||
* @param bounds are the surfaces delineating what's inside the shape.
|
* @param bounds are the surfaces delineating what's inside the shape.
|
||||||
*/
|
*/
|
||||||
public void recordBounds(final Plane q, final Bounds boundsInfo, final Membership... bounds) {
|
public void recordBounds(final PlanetModel planetModel, final Plane q, final Bounds boundsInfo, final Membership... bounds) {
|
||||||
final GeoPoint[] intersectionPoints = findIntersections(q, bounds, NO_BOUNDS);
|
final GeoPoint[] intersectionPoints = findIntersections(planetModel, q, bounds, NO_BOUNDS);
|
||||||
for (GeoPoint intersectionPoint : intersectionPoints) {
|
for (GeoPoint intersectionPoint : intersectionPoints) {
|
||||||
boundsInfo.addPoint(intersectionPoint);
|
boundsInfo.addPoint(intersectionPoint);
|
||||||
}
|
}
|
||||||
|
@ -430,10 +470,11 @@ public class Plane extends Vector {
|
||||||
* Updates both latitude and longitude information, using max/min points found
|
* Updates both latitude and longitude information, using max/min points found
|
||||||
* within the specified bounds.
|
* within the specified bounds.
|
||||||
*
|
*
|
||||||
|
* @param planetModel is the planet model to use in determining bounds.
|
||||||
* @param boundsInfo is the info to update with additional bounding information.
|
* @param boundsInfo is the info to update with additional bounding information.
|
||||||
* @param bounds are the surfaces delineating what's inside the shape.
|
* @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
|
// For clarity, load local variables with good names
|
||||||
final double A = this.x;
|
final double A = this.x;
|
||||||
final double B = this.y;
|
final double B = this.y;
|
||||||
|
@ -442,236 +483,27 @@ public class Plane extends Vector {
|
||||||
// Now compute latitude min/max points
|
// Now compute latitude min/max points
|
||||||
if (!boundsInfo.checkNoTopLatitudeBound() || !boundsInfo.checkNoBottomLatitudeBound()) {
|
if (!boundsInfo.checkNoTopLatitudeBound() || !boundsInfo.checkNoBottomLatitudeBound()) {
|
||||||
//System.err.println("Looking at latitude for plane "+this);
|
//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)) {
|
if ((Math.abs(A) >= MINIMUM_RESOLUTION || Math.abs(B) >= MINIMUM_RESOLUTION)) {
|
||||||
//System.out.println("A = "+A+" B = "+B+" C = "+C+" D = "+D);
|
// NOT a horizontal circle!
|
||||||
// sin (phi) = z
|
//System.err.println(" Not a horizontal circle");
|
||||||
// cos (theta - phi) = D
|
final Plane verticalPlane = constructNormalizedVerticalPlane(A,B);
|
||||||
// sin (theta) = C (the dot product of (0,0,1) and (A,B,C) )
|
final GeoPoint[] points = findIntersections(planetModel, verticalPlane, NO_BOUNDS, NO_BOUNDS);
|
||||||
// Q: what is z?
|
for (final GeoPoint point : points) {
|
||||||
//
|
addPoint(boundsInfo, bounds, point.x, point.y, point.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Horizontal circle.
|
// Horizontal circle. Since a==b, one vertical plane suffices.
|
||||||
// Since the recordBounds() method will be called ONLY for planes that constitute edges of a shape,
|
final Plane verticalPlane = new Plane(1.0,0.0);
|
||||||
// we can be sure that some part of the horizontal circle will be part of the boundary, so we don't need
|
final GeoPoint[] points = findIntersections(planetModel, verticalPlane, NO_BOUNDS, NO_BOUNDS);
|
||||||
// to check Membership objects.
|
// There will always be two points; we only need one.
|
||||||
boundsInfo.addHorizontalCircle(-D * C);
|
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");
|
//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
|
// 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
|
// 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
|
// 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
|
// 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 unit circle and the line
|
// need to do then is to find the intersection of the projected ellipse and the line
|
||||||
// equation:
|
// equation:
|
||||||
//
|
//
|
||||||
// A x + B y + D = 0
|
// A x + B y + D = 0
|
||||||
|
@ -706,20 +538,20 @@ public class Plane extends Vector {
|
||||||
// Since A != 0:
|
// Since A != 0:
|
||||||
// x = (-By - D)/A
|
// x = (-By - D)/A
|
||||||
//
|
//
|
||||||
// The unit circle:
|
// The projected ellipse:
|
||||||
// x^2 + y^2 - 1 = 0
|
// x^2/a^2 + y^2/b^2 - 1 = 0
|
||||||
// Substitute:
|
// 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:
|
// 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:
|
// 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:
|
// 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;
|
a = B * B * planetModel.inverseAbSquared + A * A * planetModel.inverseAbSquared;
|
||||||
b = 2.0 * B * D;
|
b = 2.0 * B * D * planetModel.inverseAbSquared;
|
||||||
c = D * D - A * A;
|
c = D * D * planetModel.inverseAbSquared - A * A;
|
||||||
|
|
||||||
double sqrtClause = b * b - 4.0 * a * c;
|
double sqrtClause = b * b - 4.0 * a * c;
|
||||||
|
|
||||||
|
@ -750,9 +582,9 @@ public class Plane extends Vector {
|
||||||
// Use equation suitable for B != 0
|
// Use equation suitable for B != 0
|
||||||
// Since I != 0, we rewrite:
|
// Since I != 0, we rewrite:
|
||||||
// y = (-Ax - D)/B
|
// y = (-Ax - D)/B
|
||||||
a = B * B + A * A;
|
a = B * B * planetModel.inverseAbSquared + A * A * planetModel.inverseAbSquared;
|
||||||
b = 2.0 * A * D;
|
b = 2.0 * A * D * planetModel.inverseAbSquared;
|
||||||
c = D * D - B * B;
|
c = D * D * planetModel.inverseAbSquared - B * B;
|
||||||
|
|
||||||
double sqrtClause = b * b - 4.0 * a * c;
|
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,
|
// 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.
|
// 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:
|
// From plane:
|
||||||
// z = (-Ax - By - D) / C
|
// z = (-Ax - By - D) / C
|
||||||
// From unit sphere:
|
// From ellipsoid:
|
||||||
// x^2 + y^2 + [(-Ax - By - D) / C]^2 = 1
|
// x^2/a^2 + y^2/b^2 + [(-Ax - By - D) / C]^2/c^2 = 1
|
||||||
// Simplify/expand:
|
// 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:
|
// 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.
|
// 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
|
// E x^2 + F y^2 + G xy + H x + I y + J = 0
|
||||||
double E = A * A + C * C;
|
double E = A * A * planetModel.inverseCSquared + C * C * planetModel.inverseAbSquared;
|
||||||
double F = B * B + C * C;
|
double F = B * B * planetModel.inverseCSquared + C * C * planetModel.inverseAbSquared;
|
||||||
double G = 2.0 * A * B;
|
double G = 2.0 * A * B * planetModel.inverseCSquared;
|
||||||
double H = 2.0 * A * D;
|
double H = 2.0 * A * D * planetModel.inverseCSquared;
|
||||||
double I = 2.0 * B * D;
|
double I = 2.0 * B * D * planetModel.inverseCSquared;
|
||||||
double J = D * D - C * C;
|
double J = D * D * planetModel.inverseCSquared - C * C;
|
||||||
|
|
||||||
//System.err.println("E = " + E + " F = " + F + " G = " + G + " H = "+ H + " I = " + I + " J = " + J);
|
//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
|
* Determine whether the plane intersects another plane within the
|
||||||
* bounds provided.
|
* bounds provided.
|
||||||
*
|
*
|
||||||
|
* @param planetModel is the planet model to use in determining intersection.
|
||||||
* @param q is the other plane.
|
* @param q is the other plane.
|
||||||
* @param notablePoints are points to look at to disambiguate cases when the two planes are identical.
|
* @param notablePoints are points to look at to disambiguate cases when the two planes are identical.
|
||||||
* @param moreNotablePoints are additional points to look at to disambiguate cases when the two planes are identical.
|
* @param 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.
|
* @param moreBounds are more bounds.
|
||||||
* @return true if there's an intersection.
|
* @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);
|
//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.
|
// 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
|
// 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");
|
//System.err.println(" no notable points inside found; no intersection");
|
||||||
return false;
|
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.
|
* Find a sample point on the intersection between two planes and the unit sphere.
|
||||||
*/
|
*/
|
||||||
public GeoPoint getSampleIntersectionPoint(final Plane q) {
|
public GeoPoint getSampleIntersectionPoint(final PlanetModel planetModel, final Plane q) {
|
||||||
final GeoPoint[] intersections = findIntersections(q, NO_BOUNDS, NO_BOUNDS);
|
final GeoPoint[] intersections = findIntersections(planetModel, q, NO_BOUNDS, NO_BOUNDS);
|
||||||
if (intersections.length == 0)
|
if (intersections.length == 0)
|
||||||
return null;
|
return null;
|
||||||
return intersections[0];
|
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.
|
* Construct a sided plane from a point and a Z coordinate.
|
||||||
*
|
*
|
||||||
* @param p point to evaluate.
|
* @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) {
|
public SidedPlane(Vector p, final PlanetModel planetModel, double sinLat) {
|
||||||
super(height);
|
super(planetModel, sinLat);
|
||||||
sigNum = Math.signum(evaluate(p));
|
sigNum = Math.signum(evaluate(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +85,28 @@ public class SidedPlane extends Plane implements Membership {
|
||||||
sigNum = Math.signum(evaluate(p));
|
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.
|
* Check if a point is within this shape.
|
||||||
*
|
*
|
||||||
|
|
|
@ -114,14 +114,20 @@ public class Vector {
|
||||||
*/
|
*/
|
||||||
public boolean isWithin(final Membership[] bounds, final Membership[] moreBounds) {
|
public boolean isWithin(final Membership[] bounds, final Membership[] moreBounds) {
|
||||||
// Return true if the point described is within all provided bounds
|
// Return true if the point described is within all provided bounds
|
||||||
|
//System.err.println(" checking if "+this+" is within bounds");
|
||||||
for (Membership bound : 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for (Membership bound : moreBounds) {
|
for (Membership bound : moreBounds) {
|
||||||
if (bound != null && !bound.isWithin(this))
|
if (bound != null && !bound.isWithin(this)) {
|
||||||
|
//System.err.println(" NOT within "+bound);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
//System.err.println(" is within");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,6 +307,28 @@ public class Vector {
|
||||||
return Math.sqrt(x * x + y * y + z * z);
|
return Math.sqrt(x * x + y * y + z * z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Compute the desired magnitude of a unit vector projected to a given
|
||||||
|
* planet model.
|
||||||
|
* @param planetModel is the planet model.
|
||||||
|
* @param x is the unit vector x value.
|
||||||
|
* @param y is the unit vector y value.
|
||||||
|
* @param z is the unit vector z value.
|
||||||
|
* @return a magnitude value for that (x,y,z) that projects the vector onto the specified ellipsoid.
|
||||||
|
*/
|
||||||
|
protected static double computeDesiredEllipsoidMagnitude(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 desired magnitude of a unit vector projected to a given
|
||||||
|
* planet model. The unit vector is specified only by a z value.
|
||||||
|
* @param planetModel is the planet model.
|
||||||
|
* @param z is the unit vector z value.
|
||||||
|
* @return a magnitude value for that z value that projects the vector onto the specified ellipsoid.
|
||||||
|
*/
|
||||||
|
protected static double computeDesiredEllipsoidMagnitude(final PlanetModel planetModel, final double z) {
|
||||||
|
return 1.0 / Math.sqrt((1.0-z*z)*planetModel.inverseAbSquared + z*z*planetModel.inverseCSquared);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (!(o instanceof Vector))
|
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.GeoPoint;
|
||||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoPolygonFactory;
|
import org.apache.lucene.spatial.spatial4j.geo3d.GeoPolygonFactory;
|
||||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoShape;
|
import org.apache.lucene.spatial.spatial4j.geo3d.GeoShape;
|
||||||
|
import org.apache.lucene.spatial.spatial4j.geo3d.PlanetModel;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static com.spatial4j.core.distance.DistanceUtils.DEGREES_TO_RADIANS;
|
import static com.spatial4j.core.distance.DistanceUtils.DEGREES_TO_RADIANS;
|
||||||
|
@ -81,12 +82,12 @@ public class Geo3dRptTest extends RandomSpatialOpStrategyTestCase {
|
||||||
public void testFailure1() throws IOException {
|
public void testFailure1() throws IOException {
|
||||||
setupStrategy();
|
setupStrategy();
|
||||||
final List<GeoPoint> points = new ArrayList<GeoPoint>();
|
final List<GeoPoint> points = new ArrayList<GeoPoint>();
|
||||||
points.add(new GeoPoint(18 * DEGREES_TO_RADIANS, -27 * DEGREES_TO_RADIANS));
|
points.add(new GeoPoint(PlanetModel.SPHERE, 18 * DEGREES_TO_RADIANS, -27 * DEGREES_TO_RADIANS));
|
||||||
points.add(new GeoPoint(-57 * DEGREES_TO_RADIANS, 146 * DEGREES_TO_RADIANS));
|
points.add(new GeoPoint(PlanetModel.SPHERE, -57 * DEGREES_TO_RADIANS, 146 * DEGREES_TO_RADIANS));
|
||||||
points.add(new GeoPoint(14 * DEGREES_TO_RADIANS, -180 * DEGREES_TO_RADIANS));
|
points.add(new GeoPoint(PlanetModel.SPHERE, 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, -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);
|
final Rectangle rect = ctx.makeRectangle(-49, -45, 73, 86);
|
||||||
testOperation(rect,SpatialOperation.Intersects,triangle, false);
|
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) {
|
private Shape makeTriangle(double x1, double y1, double x2, double y2, double x3, double y3) {
|
||||||
final List<GeoPoint> geoPoints = new ArrayList<>();
|
final List<GeoPoint> geoPoints = new ArrayList<>();
|
||||||
geoPoints.add(new GeoPoint(y1 * DEGREES_TO_RADIANS, x1 * DEGREES_TO_RADIANS));
|
geoPoints.add(new GeoPoint(PlanetModel.SPHERE, y1 * DEGREES_TO_RADIANS, x1 * DEGREES_TO_RADIANS));
|
||||||
geoPoints.add(new GeoPoint(y2 * DEGREES_TO_RADIANS, x2 * DEGREES_TO_RADIANS));
|
geoPoints.add(new GeoPoint(PlanetModel.SPHERE, 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, y3 * DEGREES_TO_RADIANS, x3 * DEGREES_TO_RADIANS));
|
||||||
final int convexPointIndex = 0;
|
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);
|
return new Geo3dShape(shape, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,12 +126,12 @@ public class Geo3dRptTest extends RandomSpatialOpStrategyTestCase {
|
||||||
final List<GeoPoint> geoPoints = new ArrayList<>();
|
final List<GeoPoint> geoPoints = new ArrayList<>();
|
||||||
while (geoPoints.size() < vertexCount) {
|
while (geoPoints.size() < vertexCount) {
|
||||||
final Point point = randomPoint();
|
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);
|
geoPoints.add(gPt);
|
||||||
}
|
}
|
||||||
final int convexPointIndex = random().nextInt(vertexCount); //If we get this wrong, hopefully we get IllegalArgumentException
|
final int convexPointIndex = random().nextInt(vertexCount); //If we get this wrong, hopefully we get IllegalArgumentException
|
||||||
try {
|
try {
|
||||||
final GeoShape shape = GeoPolygonFactory.makeGeoPolygon(geoPoints, convexPointIndex);
|
final GeoShape shape = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, geoPoints, convexPointIndex);
|
||||||
return new Geo3dShape(shape, ctx);
|
return new Geo3dShape(shape, ctx);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// This is what happens when we create a shape that is invalid. Although it is conceivable that there are cases where
|
// 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 int circleRadius = random().nextInt(179) + 1;
|
||||||
final Point point = randomPoint();
|
final Point point = randomPoint();
|
||||||
try {
|
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);
|
circleRadius * DEGREES_TO_RADIANS);
|
||||||
return new Geo3dShape(shape, ctx);
|
return new Geo3dShape(shape, ctx);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
@ -167,7 +168,7 @@ public class Geo3dRptTest extends RandomSpatialOpStrategyTestCase {
|
||||||
lrhcPoint = temp;
|
lrhcPoint = temp;
|
||||||
}
|
}
|
||||||
try {
|
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,
|
lrhcPoint.getY() * DEGREES_TO_RADIANS,
|
||||||
ulhcPoint.getX() * DEGREES_TO_RADIANS,
|
ulhcPoint.getX() * DEGREES_TO_RADIANS,
|
||||||
lrhcPoint.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;
|
final double width = (random().nextInt(89)+1) * DEGREES_TO_RADIANS;
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
final GeoPath path = new GeoPath(width);
|
final GeoPath path = new GeoPath(PlanetModel.SPHERE, width);
|
||||||
for (int i = 0; i < pointCount; i++) {
|
for (int i = 0; i < pointCount; i++) {
|
||||||
final Point nextPoint = randomPoint();
|
final Point nextPoint = randomPoint();
|
||||||
path.addPoint(nextPoint.getY() * DEGREES_TO_RADIANS, nextPoint.getX() * DEGREES_TO_RADIANS);
|
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.context.SpatialContext;
|
||||||
import com.spatial4j.core.distance.DistanceUtils;
|
import com.spatial4j.core.distance.DistanceUtils;
|
||||||
import com.spatial4j.core.shape.Point;
|
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.Bounds;
|
||||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoArea;
|
|
||||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoBBox;
|
import org.apache.lucene.spatial.spatial4j.geo3d.GeoBBox;
|
||||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoBBoxFactory;
|
import org.apache.lucene.spatial.spatial4j.geo3d.GeoBBoxFactory;
|
||||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoCircle;
|
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.GeoPoint;
|
||||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoPolygonFactory;
|
import org.apache.lucene.spatial.spatial4j.geo3d.GeoPolygonFactory;
|
||||||
import org.apache.lucene.spatial.spatial4j.geo3d.GeoShape;
|
import org.apache.lucene.spatial.spatial4j.geo3d.GeoShape;
|
||||||
|
import org.apache.lucene.spatial.spatial4j.geo3d.PlanetModel;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static com.spatial4j.core.distance.DistanceUtils.DEGREES_TO_RADIANS;
|
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
|
@Rule
|
||||||
public final LogRule testLog = LogRule.instance;
|
public final LogRule testLog = LogRule.instance;
|
||||||
|
|
||||||
static Random random() {
|
protected static Random random() {
|
||||||
return RandomizedContext.current().getRandom();
|
return RandomizedContext.current().getRandom();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
protected final PlanetModel planetModel;
|
||||||
ctx = SpatialContext.GEO;
|
|
||||||
|
public Geo3dShapeRectRelationTestCase(PlanetModel planetModel) {
|
||||||
|
super(SpatialContext.GEO);
|
||||||
|
this.planetModel = planetModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final static double RADIANS_PER_DEGREE = Math.PI/180.0;
|
protected GeoBBox getBoundingBox(final GeoShape path) {
|
||||||
|
|
||||||
protected static GeoBBox getBoundingBox(final GeoShape path) {
|
|
||||||
Bounds bounds = path.getBounds(null);
|
Bounds bounds = path.getBounds(null);
|
||||||
|
|
||||||
double leftLon;
|
double leftLon;
|
||||||
|
@ -78,7 +80,7 @@ public class Geo3dShapeRectRelationTest extends RandomizedShapeTestCase {
|
||||||
} else {
|
} else {
|
||||||
maxLat = bounds.getMaxLatitude().doubleValue();
|
maxLat = bounds.getMaxLatitude().doubleValue();
|
||||||
}
|
}
|
||||||
return GeoBBoxFactory.makeGeoBBox(maxLat, minLat, leftLon, rightLon);
|
return GeoBBoxFactory.makeGeoBBox(planetModel, maxLat, minLat, leftLon, rightLon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -91,9 +93,9 @@ public class Geo3dShapeRectRelationTest extends RandomizedShapeTestCase {
|
||||||
final int circleRadius = random().nextInt(179) + 1;//no 0-radius
|
final int circleRadius = random().nextInt(179) + 1;//no 0-radius
|
||||||
final Point point = nearP;
|
final Point point = nearP;
|
||||||
try {
|
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);
|
circleRadius * DEGREES_TO_RADIANS);
|
||||||
return new Geo3dShape(shape, ctx);
|
return new Geo3dShape(planetModel, shape, ctx);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// This is what happens when we create a shape that is invalid. Although it is conceivable that there are cases where
|
// 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.
|
// 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;
|
ulhcPoint = lrhcPoint;
|
||||||
lrhcPoint = temp;
|
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,
|
lrhcPoint.getY() * DEGREES_TO_RADIANS,
|
||||||
ulhcPoint.getX() * DEGREES_TO_RADIANS,
|
ulhcPoint.getX() * DEGREES_TO_RADIANS,
|
||||||
lrhcPoint.getX() * DEGREES_TO_RADIANS);
|
lrhcPoint.getX() * DEGREES_TO_RADIANS);
|
||||||
return new Geo3dShape(shape, ctx);
|
return new Geo3dShape(planetModel, shape, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -160,13 +162,13 @@ public class Geo3dShapeRectRelationTest extends RandomizedShapeTestCase {
|
||||||
final Point point = randomPoint();
|
final Point point = randomPoint();
|
||||||
if (ctx.getDistCalc().distance(point,centerPoint) > maxDistance)
|
if (ctx.getDistCalc().distance(point,centerPoint) > maxDistance)
|
||||||
continue;
|
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);
|
geoPoints.add(gPt);
|
||||||
}
|
}
|
||||||
final int convexPointIndex = random().nextInt(vertexCount); //If we get this wrong, hopefully we get IllegalArgumentException
|
final int convexPointIndex = random().nextInt(vertexCount); //If we get this wrong, hopefully we get IllegalArgumentException
|
||||||
try {
|
try {
|
||||||
final GeoShape shape = GeoPolygonFactory.makeGeoPolygon(geoPoints, convexPointIndex);
|
final GeoShape shape = GeoPolygonFactory.makeGeoPolygon(planetModel, geoPoints, convexPointIndex);
|
||||||
return new Geo3dShape(shape, ctx);
|
return new Geo3dShape(planetModel, shape, ctx);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// This is what happens when we create a shape that is invalid. Although it is conceivable that there are cases where
|
// 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.
|
// 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;
|
final double width = (random().nextInt(89)+1) * DEGREES_TO_RADIANS;
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
final GeoPath path = new GeoPath(width);
|
final GeoPath path = new GeoPath(planetModel, width);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < pointCount) {
|
while (i < pointCount) {
|
||||||
final Point nextPoint = randomPoint();
|
final Point nextPoint = randomPoint();
|
||||||
|
@ -211,7 +213,7 @@ public class Geo3dShapeRectRelationTest extends RandomizedShapeTestCase {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
path.done();
|
path.done();
|
||||||
return new Geo3dShape(path, ctx);
|
return new Geo3dShape(planetModel, path, ctx);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// This is what happens when we create a shape that is invalid. Although it is conceivable that there are cases where
|
// 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.
|
// the exception is thrown incorrectly, we aren't going to be able to do that in this random test.
|
||||||
|
@ -235,41 +237,7 @@ public class Geo3dShapeRectRelationTest extends RandomizedShapeTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Point geoPointToSpatial4jPoint(GeoPoint geoPoint) {
|
private Point geoPointToSpatial4jPoint(GeoPoint geoPoint) {
|
||||||
return ctx.makePoint(geoPoint.x * DistanceUtils.RADIANS_TO_DEGREES,
|
return ctx.makePoint(geoPoint.getLongitude() * DistanceUtils.RADIANS_TO_DEGREES,
|
||||||
geoPoint.y * DistanceUtils.RADIANS_TO_DEGREES);
|
geoPoint.getLongitude() * 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;
|
GeoConvexPolygon cp;
|
||||||
int relationship;
|
int relationship;
|
||||||
List<GeoPoint> points = new ArrayList<GeoPoint>();
|
List<GeoPoint> points = new ArrayList<GeoPoint>();
|
||||||
points.add(new GeoPoint(24 * DEGREES_TO_RADIANS, -30 * DEGREES_TO_RADIANS));
|
points.add(new GeoPoint(PlanetModel.SPHERE, 24 * DEGREES_TO_RADIANS, -30 * DEGREES_TO_RADIANS));
|
||||||
points.add(new GeoPoint(-11 * DEGREES_TO_RADIANS, 101 * DEGREES_TO_RADIANS));
|
points.add(new GeoPoint(PlanetModel.SPHERE, -11 * DEGREES_TO_RADIANS, 101 * DEGREES_TO_RADIANS));
|
||||||
points.add(new GeoPoint(-49 * DEGREES_TO_RADIANS, -176 * DEGREES_TO_RADIANS));
|
points.add(new GeoPoint(PlanetModel.SPHERE, -49 * DEGREES_TO_RADIANS, -176 * DEGREES_TO_RADIANS));
|
||||||
GeoMembershipShape shape = GeoPolygonFactory.makeGeoPolygon(points, 0);
|
GeoMembershipShape shape = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points, 0);
|
||||||
box = GeoBBoxFactory.makeGeoBBox(-64 * DEGREES_TO_RADIANS, -64 * DEGREES_TO_RADIANS, -180 * DEGREES_TO_RADIANS, 180 * DEGREES_TO_RADIANS);
|
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);
|
relationship = box.getRelationship(shape);
|
||||||
assertEquals(GeoArea.CONTAINS, relationship);
|
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);
|
System.out.println("Shape = " + shape + " Rect = " + box);
|
||||||
relationship = box.getRelationship(shape);
|
relationship = box.getRelationship(shape);
|
||||||
assertEquals(GeoArea.CONTAINS, relationship);
|
assertEquals(GeoArea.CONTAINS, relationship);
|
||||||
|
@ -54,52 +54,52 @@ public class GeoBBoxTest {
|
||||||
GeoBBox box;
|
GeoBBox box;
|
||||||
GeoPoint gp;
|
GeoPoint gp;
|
||||||
// Standard normal Rect box, not crossing dateline
|
// 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);
|
||||||
gp = new GeoPoint(-0.1, 0.0);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 0.0);
|
||||||
assertTrue(box.isWithin(gp));
|
assertTrue(box.isWithin(gp));
|
||||||
gp = new GeoPoint(0.1, 0.0);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.1, 0.0);
|
||||||
assertFalse(box.isWithin(gp));
|
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));
|
assertFalse(box.isWithin(gp));
|
||||||
gp = new GeoPoint(-0.1, 1.1);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 1.1);
|
||||||
assertFalse(box.isWithin(gp));
|
assertFalse(box.isWithin(gp));
|
||||||
gp = new GeoPoint(-0.1, -1.1);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -1.1);
|
||||||
assertFalse(box.isWithin(gp));
|
assertFalse(box.isWithin(gp));
|
||||||
// Standard normal Rect box, crossing dateline
|
// Standard normal Rect box, crossing dateline
|
||||||
box = GeoBBoxFactory.makeGeoBBox(0.0, -Math.PI * 0.25, Math.PI - 1.0, -Math.PI + 1.0);
|
box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, Math.PI - 1.0, -Math.PI + 1.0);
|
||||||
gp = new GeoPoint(-0.1, -Math.PI);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI);
|
||||||
assertTrue(box.isWithin(gp));
|
assertTrue(box.isWithin(gp));
|
||||||
gp = new GeoPoint(0.1, -Math.PI);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.1, -Math.PI);
|
||||||
assertFalse(box.isWithin(gp));
|
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));
|
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));
|
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));
|
assertFalse(box.isWithin(gp));
|
||||||
// Latitude zone rectangle
|
// Latitude zone rectangle
|
||||||
box = GeoBBoxFactory.makeGeoBBox(0.0, -Math.PI * 0.25, -Math.PI, Math.PI);
|
box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 0.0, -Math.PI * 0.25, -Math.PI, Math.PI);
|
||||||
gp = new GeoPoint(-0.1, -Math.PI);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI);
|
||||||
assertTrue(box.isWithin(gp));
|
assertTrue(box.isWithin(gp));
|
||||||
gp = new GeoPoint(0.1, -Math.PI);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.1, -Math.PI);
|
||||||
assertFalse(box.isWithin(gp));
|
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));
|
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));
|
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));
|
assertTrue(box.isWithin(gp));
|
||||||
// World
|
// World
|
||||||
box = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, Math.PI);
|
box = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, Math.PI);
|
||||||
gp = new GeoPoint(-0.1, -Math.PI);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -Math.PI);
|
||||||
assertTrue(box.isWithin(gp));
|
assertTrue(box.isWithin(gp));
|
||||||
gp = new GeoPoint(0.1, -Math.PI);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.1, -Math.PI);
|
||||||
assertTrue(box.isWithin(gp));
|
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));
|
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));
|
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));
|
assertTrue(box.isWithin(gp));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -109,23 +109,23 @@ public class GeoBBoxTest {
|
||||||
GeoBBox box;
|
GeoBBox box;
|
||||||
GeoPoint gp;
|
GeoPoint gp;
|
||||||
// Standard normal Rect box, not crossing dateline
|
// 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);
|
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));
|
assertTrue(box.isWithin(gp));
|
||||||
gp = new GeoPoint(0.15, 0.0);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.15, 0.0);
|
||||||
assertFalse(box.isWithin(gp));
|
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));
|
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));
|
assertFalse(box.isWithin(gp));
|
||||||
gp = new GeoPoint(-0.1, -1.05);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -1.05);
|
||||||
assertTrue(box.isWithin(gp));
|
assertTrue(box.isWithin(gp));
|
||||||
gp = new GeoPoint(-0.1, -1.15);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, -1.15);
|
||||||
assertFalse(box.isWithin(gp));
|
assertFalse(box.isWithin(gp));
|
||||||
gp = new GeoPoint(-0.1, 1.05);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 1.05);
|
||||||
assertTrue(box.isWithin(gp));
|
assertTrue(box.isWithin(gp));
|
||||||
gp = new GeoPoint(-0.1, 1.15);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.1, 1.15);
|
||||||
assertFalse(box.isWithin(gp));
|
assertFalse(box.isWithin(gp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ public class GeoBBoxTest {
|
||||||
GeoBBox c;
|
GeoBBox c;
|
||||||
Bounds b;
|
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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
|
@ -145,7 +145,7 @@ public class GeoBBoxTest {
|
||||||
assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
|
assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
|
||||||
assertEquals(0.0, b.getMaxLatitude(), 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);
|
b = c.getBounds(null);
|
||||||
assertTrue(b.checkNoLongitudeBound());
|
assertTrue(b.checkNoLongitudeBound());
|
||||||
|
@ -156,7 +156,7 @@ public class GeoBBoxTest {
|
||||||
assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
|
assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
|
||||||
assertEquals(0.0, b.getMaxLatitude(), 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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
|
@ -165,7 +165,7 @@ public class GeoBBoxTest {
|
||||||
assertEquals(-1.0, b.getLeftLongitude(), 0.000001);
|
assertEquals(-1.0, b.getLeftLongitude(), 0.000001);
|
||||||
assertEquals(1.0, b.getRightLongitude(), 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);
|
b = c.getBounds(null);
|
||||||
assertTrue(b.checkNoLongitudeBound());
|
assertTrue(b.checkNoLongitudeBound());
|
||||||
|
@ -176,7 +176,7 @@ public class GeoBBoxTest {
|
||||||
|
|
||||||
// Check wide variants of rectangle and longitude slice
|
// 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);
|
b = c.getBounds(null);
|
||||||
assertTrue(b.checkNoLongitudeBound());
|
assertTrue(b.checkNoLongitudeBound());
|
||||||
|
@ -187,7 +187,7 @@ public class GeoBBoxTest {
|
||||||
assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
|
assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
|
||||||
assertEquals(0.0, b.getMaxLatitude(), 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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
|
@ -198,7 +198,7 @@ public class GeoBBoxTest {
|
||||||
assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
|
assertEquals(-Math.PI * 0.25, b.getMinLatitude(), 0.000001);
|
||||||
assertEquals(0.0, b.getMaxLatitude(), 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);
|
b = c.getBounds(null);
|
||||||
assertTrue(b.checkNoLongitudeBound());
|
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.getLeftLongitude(),0.000001);
|
||||||
//assertEquals(Math.PI-0.1,b.getRightLongitude(),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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
|
@ -217,7 +217,7 @@ public class GeoBBoxTest {
|
||||||
assertEquals(-Math.PI + 0.1, b.getRightLongitude(), 0.000001);
|
assertEquals(-Math.PI + 0.1, b.getRightLongitude(), 0.000001);
|
||||||
|
|
||||||
// Check latitude zone
|
// 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);
|
b = c.getBounds(null);
|
||||||
assertTrue(b.checkNoLongitudeBound());
|
assertTrue(b.checkNoLongitudeBound());
|
||||||
|
@ -230,8 +230,8 @@ public class GeoBBoxTest {
|
||||||
GeoBBox c1;
|
GeoBBox c1;
|
||||||
GeoBBox c2;
|
GeoBBox c2;
|
||||||
|
|
||||||
c1 = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, 0.0);
|
c1 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 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);
|
c2 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI);
|
||||||
|
|
||||||
b = new Bounds();
|
b = new Bounds();
|
||||||
b = c1.getBounds(b);
|
b = c1.getBounds(b);
|
||||||
|
@ -240,8 +240,8 @@ public class GeoBBoxTest {
|
||||||
assertTrue(b.checkNoTopLatitudeBound());
|
assertTrue(b.checkNoTopLatitudeBound());
|
||||||
assertTrue(b.checkNoBottomLatitudeBound());
|
assertTrue(b.checkNoBottomLatitudeBound());
|
||||||
|
|
||||||
c1 = GeoBBoxFactory.makeGeoBBox(Math.PI * 0.5, -Math.PI * 0.5, -Math.PI, 0.0);
|
c1 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 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);
|
c2 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI * 0.5);
|
||||||
|
|
||||||
b = new Bounds();
|
b = new Bounds();
|
||||||
b = c1.getBounds(b);
|
b = c1.getBounds(b);
|
||||||
|
@ -252,8 +252,8 @@ public class GeoBBoxTest {
|
||||||
//assertEquals(-Math.PI,b.getLeftLongitude(),0.000001);
|
//assertEquals(-Math.PI,b.getLeftLongitude(),0.000001);
|
||||||
//assertEquals(Math.PI*0.5,b.getRightLongitude(),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);
|
c1 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, 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);
|
c2 = GeoBBoxFactory.makeGeoBBox(PlanetModel.SPHERE, Math.PI * 0.5, -Math.PI * 0.5, 0.0, Math.PI);
|
||||||
|
|
||||||
b = new Bounds();
|
b = new Bounds();
|
||||||
b = c1.getBounds(b);
|
b = c1.getBounds(b);
|
||||||
|
|
|
@ -30,16 +30,16 @@ public class GeoCircleTest {
|
||||||
public void testCircleDistance() {
|
public void testCircleDistance() {
|
||||||
GeoCircle c;
|
GeoCircle c;
|
||||||
GeoPoint gp;
|
GeoPoint gp;
|
||||||
c = new GeoCircle(0.0, -0.5, 0.1);
|
c = new GeoCircle(PlanetModel.SPHERE, 0.0, -0.5, 0.1);
|
||||||
gp = new GeoPoint(0.0, 0.0);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
|
||||||
assertEquals(Double.MAX_VALUE, c.computeArcDistance(gp), 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.computeLinearDistance(gp), 0.0);
|
||||||
assertEquals(Double.MAX_VALUE, c.computeNormalDistance(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.computeArcDistance(gp), 0.000001);
|
||||||
assertEquals(0.0, c.computeLinearDistance(gp), 0.000001);
|
assertEquals(0.0, c.computeLinearDistance(gp), 0.000001);
|
||||||
assertEquals(0.0, c.computeNormalDistance(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.05, c.computeArcDistance(gp), 0.000001);
|
||||||
assertEquals(0.049995, c.computeLinearDistance(gp), 0.000001);
|
assertEquals(0.049995, c.computeLinearDistance(gp), 0.000001);
|
||||||
assertEquals(0.049979, c.computeNormalDistance(gp), 0.000001);
|
assertEquals(0.049979, c.computeNormalDistance(gp), 0.000001);
|
||||||
|
@ -49,18 +49,18 @@ public class GeoCircleTest {
|
||||||
public void testCirclePointWithin() {
|
public void testCirclePointWithin() {
|
||||||
GeoCircle c;
|
GeoCircle c;
|
||||||
GeoPoint gp;
|
GeoPoint gp;
|
||||||
c = new GeoCircle(0.0, -0.5, 0.1);
|
c = new GeoCircle(PlanetModel.SPHERE, 0.0, -0.5, 0.1);
|
||||||
gp = new GeoPoint(0.0, 0.0);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
|
||||||
assertFalse(c.isWithin(gp));
|
assertFalse(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, -0.55);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, -0.45);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
|
||||||
assertTrue(c.isWithin(gp));
|
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));
|
assertFalse(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, Math.PI);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
|
||||||
assertFalse(c.isWithin(gp));
|
assertFalse(c.isWithin(gp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ public class GeoCircleTest {
|
||||||
|
|
||||||
|
|
||||||
// Vertical circle cases
|
// 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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
assertFalse(b.checkNoTopLatitudeBound());
|
assertFalse(b.checkNoTopLatitudeBound());
|
||||||
|
@ -80,7 +80,7 @@ public class GeoCircleTest {
|
||||||
assertEquals(-0.4, b.getRightLongitude(), 0.000001);
|
assertEquals(-0.4, b.getRightLongitude(), 0.000001);
|
||||||
assertEquals(-0.1, b.getMinLatitude(), 0.000001);
|
assertEquals(-0.1, b.getMinLatitude(), 0.000001);
|
||||||
assertEquals(0.1, b.getMaxLatitude(), 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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
assertFalse(b.checkNoTopLatitudeBound());
|
assertFalse(b.checkNoTopLatitudeBound());
|
||||||
|
@ -89,7 +89,7 @@ public class GeoCircleTest {
|
||||||
assertEquals(0.6, b.getRightLongitude(), 0.000001);
|
assertEquals(0.6, b.getRightLongitude(), 0.000001);
|
||||||
assertEquals(-0.1, b.getMinLatitude(), 0.000001);
|
assertEquals(-0.1, b.getMinLatitude(), 0.000001);
|
||||||
assertEquals(0.1, b.getMaxLatitude(), 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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
assertFalse(b.checkNoTopLatitudeBound());
|
assertFalse(b.checkNoTopLatitudeBound());
|
||||||
|
@ -98,7 +98,7 @@ public class GeoCircleTest {
|
||||||
assertEquals(0.1, b.getRightLongitude(), 0.000001);
|
assertEquals(0.1, b.getRightLongitude(), 0.000001);
|
||||||
assertEquals(-0.1, b.getMinLatitude(), 0.000001);
|
assertEquals(-0.1, b.getMinLatitude(), 0.000001);
|
||||||
assertEquals(0.1, b.getMaxLatitude(), 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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
assertFalse(b.checkNoTopLatitudeBound());
|
assertFalse(b.checkNoTopLatitudeBound());
|
||||||
|
@ -108,13 +108,13 @@ public class GeoCircleTest {
|
||||||
assertEquals(-0.1, b.getMinLatitude(), 0.000001);
|
assertEquals(-0.1, b.getMinLatitude(), 0.000001);
|
||||||
assertEquals(0.1, b.getMaxLatitude(), 0.000001);
|
assertEquals(0.1, b.getMaxLatitude(), 0.000001);
|
||||||
// Horizontal circle cases
|
// 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);
|
b = c.getBounds(null);
|
||||||
assertTrue(b.checkNoLongitudeBound());
|
assertTrue(b.checkNoLongitudeBound());
|
||||||
assertTrue(b.checkNoTopLatitudeBound());
|
assertTrue(b.checkNoTopLatitudeBound());
|
||||||
assertFalse(b.checkNoBottomLatitudeBound());
|
assertFalse(b.checkNoBottomLatitudeBound());
|
||||||
assertEquals(Math.PI * 0.5 - 0.1, b.getMinLatitude(), 0.000001);
|
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);
|
b = c.getBounds(null);
|
||||||
assertTrue(b.checkNoLongitudeBound());
|
assertTrue(b.checkNoLongitudeBound());
|
||||||
assertFalse(b.checkNoTopLatitudeBound());
|
assertFalse(b.checkNoTopLatitudeBound());
|
||||||
|
@ -122,7 +122,7 @@ public class GeoCircleTest {
|
||||||
assertEquals(-Math.PI * 0.5 + 0.1, b.getMaxLatitude(), 0.000001);
|
assertEquals(-Math.PI * 0.5 + 0.1, b.getMaxLatitude(), 0.000001);
|
||||||
|
|
||||||
// Now do a somewhat tilted plane, facing different directions.
|
// 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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
assertFalse(b.checkNoTopLatitudeBound());
|
assertFalse(b.checkNoTopLatitudeBound());
|
||||||
|
@ -132,7 +132,7 @@ public class GeoCircleTest {
|
||||||
assertEquals(-0.1, b.getLeftLongitude(), 0.00001);
|
assertEquals(-0.1, b.getLeftLongitude(), 0.00001);
|
||||||
assertEquals(0.1, b.getRightLongitude(), 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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
assertFalse(b.checkNoTopLatitudeBound());
|
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.getLeftLongitude(), 0.00001);
|
||||||
assertEquals(-Math.PI + 0.1, b.getRightLongitude(), 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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
assertFalse(b.checkNoTopLatitudeBound());
|
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.getLeftLongitude(), 0.00001);
|
||||||
assertEquals(Math.PI * 0.5 + 0.1, b.getRightLongitude(), 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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
assertFalse(b.checkNoTopLatitudeBound());
|
assertFalse(b.checkNoTopLatitudeBound());
|
||||||
|
@ -163,7 +163,7 @@ public class GeoCircleTest {
|
||||||
assertEquals(-Math.PI * 0.5 + 0.1, b.getRightLongitude(), 0.00001);
|
assertEquals(-Math.PI * 0.5 + 0.1, b.getRightLongitude(), 0.00001);
|
||||||
|
|
||||||
// Slightly tilted, PI/4 direction.
|
// 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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
assertFalse(b.checkNoTopLatitudeBound());
|
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.getLeftLongitude(), 0.00001);
|
||||||
assertEquals(Math.PI * 0.25 + 0.1, b.getRightLongitude(), 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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
assertFalse(b.checkNoTopLatitudeBound());
|
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.getLeftLongitude(), 0.00001);
|
||||||
assertEquals(-Math.PI * 0.25 + 0.1, b.getRightLongitude(), 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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
assertFalse(b.checkNoTopLatitudeBound());
|
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.getLeftLongitude(), 0.00001);
|
||||||
assertEquals(Math.PI * 0.25 + 0.1, b.getRightLongitude(), 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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
assertFalse(b.checkNoTopLatitudeBound());
|
assertFalse(b.checkNoTopLatitudeBound());
|
||||||
|
@ -204,7 +204,7 @@ public class GeoCircleTest {
|
||||||
assertEquals(-Math.PI * 0.25 + 0.1, b.getRightLongitude(), 0.00001);
|
assertEquals(-Math.PI * 0.25 + 0.1, b.getRightLongitude(), 0.00001);
|
||||||
|
|
||||||
// Now do a somewhat tilted plane.
|
// 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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
assertFalse(b.checkNoTopLatitudeBound());
|
assertFalse(b.checkNoTopLatitudeBound());
|
||||||
|
|
|
@ -30,37 +30,37 @@ public class GeoConvexPolygonTest {
|
||||||
public void testPolygonPointWithin() {
|
public void testPolygonPointWithin() {
|
||||||
GeoConvexPolygon c;
|
GeoConvexPolygon c;
|
||||||
GeoPoint gp;
|
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.0, -0.6, false);
|
||||||
c.addPoint(0.1, -0.5, false);
|
c.addPoint(0.1, -0.5, false);
|
||||||
c.addPoint(0.0, -0.4, false);
|
c.addPoint(0.0, -0.4, false);
|
||||||
c.donePoints(false);
|
c.donePoints(false);
|
||||||
// Sample some points within
|
// Sample some points within
|
||||||
gp = new GeoPoint(0.0, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, -0.55);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, -0.45);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
gp = new GeoPoint(-0.05, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.05, -0.5);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.05, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.05, -0.5);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
// Sample some nearby points outside
|
// 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));
|
assertFalse(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, -0.35);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.35);
|
||||||
assertFalse(c.isWithin(gp));
|
assertFalse(c.isWithin(gp));
|
||||||
gp = new GeoPoint(-0.15, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.15, -0.5);
|
||||||
assertFalse(c.isWithin(gp));
|
assertFalse(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.15, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.15, -0.5);
|
||||||
assertFalse(c.isWithin(gp));
|
assertFalse(c.isWithin(gp));
|
||||||
// Random points outside
|
// Random points outside
|
||||||
gp = new GeoPoint(0.0, 0.0);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
|
||||||
assertFalse(c.isWithin(gp));
|
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));
|
assertFalse(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, Math.PI);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
|
||||||
assertFalse(c.isWithin(gp));
|
assertFalse(c.isWithin(gp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ public class GeoConvexPolygonTest {
|
||||||
GeoConvexPolygon c;
|
GeoConvexPolygon c;
|
||||||
Bounds b;
|
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.0, -0.6, false);
|
||||||
c.addPoint(0.1, -0.5, false);
|
c.addPoint(0.1, -0.5, false);
|
||||||
c.addPoint(0.0, -0.4, 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
|
// Start with a really simple case
|
||||||
GeoPath p;
|
GeoPath p;
|
||||||
GeoPoint gp;
|
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.0);
|
||||||
p.addPoint(0.0, 0.1);
|
p.addPoint(0.0, 0.1);
|
||||||
p.addPoint(0.0, 0.2);
|
p.addPoint(0.0, 0.2);
|
||||||
p.done();
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
assertEquals(0.0 + 0.05, p.computeArcDistance(gp), 0.000001);
|
||||||
|
|
||||||
// Compute path distances now
|
// 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.0);
|
||||||
p.addPoint(0.0, 0.1);
|
p.addPoint(0.0, 0.1);
|
||||||
p.addPoint(0.0, 0.2);
|
p.addPoint(0.0, 0.2);
|
||||||
p.done();
|
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);
|
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);
|
assertEquals(0.12, p.computeArcDistance(gp), 0.000001);
|
||||||
|
|
||||||
// Now try a vertical path, and make sure distances are as expected
|
// 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.addPoint(Math.PI * 0.25, -0.5);
|
p.addPoint(Math.PI * 0.25, -0.5);
|
||||||
p.done();
|
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);
|
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);
|
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);
|
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);
|
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
|
// Tests whether we can properly detect whether a point is within a path or not
|
||||||
GeoPath p;
|
GeoPath p;
|
||||||
GeoPoint gp;
|
GeoPoint gp;
|
||||||
p = new GeoPath(0.1);
|
p = new GeoPath(PlanetModel.SPHERE, 0.1);
|
||||||
// Build a diagonal path crossing the equator
|
// Build a diagonal path crossing the equator
|
||||||
p.addPoint(-0.2, -0.2);
|
p.addPoint(-0.2, -0.2);
|
||||||
p.addPoint(0.2, 0.2);
|
p.addPoint(0.2, 0.2);
|
||||||
p.done();
|
p.done();
|
||||||
// Test points on the path
|
// 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));
|
assertTrue(p.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, 0.0);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
|
||||||
assertTrue(p.isWithin(gp));
|
assertTrue(p.isWithin(gp));
|
||||||
gp = new GeoPoint(0.1, 0.1);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.1, 0.1);
|
||||||
assertTrue(p.isWithin(gp));
|
assertTrue(p.isWithin(gp));
|
||||||
// Test points off the path
|
// 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));
|
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));
|
assertFalse(p.isWithin(gp));
|
||||||
gp = new GeoPoint(0.2, -0.2);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.2, -0.2);
|
||||||
assertFalse(p.isWithin(gp));
|
assertFalse(p.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, Math.PI);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
|
||||||
assertFalse(p.isWithin(gp));
|
assertFalse(p.isWithin(gp));
|
||||||
// Repeat the test, but across the terminator
|
// 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
|
// Build a diagonal path crossing the equator
|
||||||
p.addPoint(-0.2, Math.PI - 0.2);
|
p.addPoint(-0.2, Math.PI - 0.2);
|
||||||
p.addPoint(0.2, -Math.PI + 0.2);
|
p.addPoint(0.2, -Math.PI + 0.2);
|
||||||
|
p.done();
|
||||||
// Test points on the path
|
// 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));
|
assertTrue(p.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, Math.PI);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
|
||||||
assertTrue(p.isWithin(gp));
|
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));
|
assertTrue(p.isWithin(gp));
|
||||||
// Test points off the path
|
// 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));
|
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));
|
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));
|
assertFalse(p.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, 0.0);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
|
||||||
assertFalse(p.isWithin(gp));
|
assertFalse(p.isWithin(gp));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -131,31 +132,31 @@ public class GeoPathTest {
|
||||||
|
|
||||||
// Start by testing the basic kinds of relationship, increasing in order of difficulty.
|
// 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.addPoint(0.3, 0.3);
|
p.addPoint(0.3, 0.3);
|
||||||
p.done();
|
p.done();
|
||||||
// Easiest: The path is wholly contains the georect
|
// 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));
|
assertEquals(GeoArea.CONTAINS, rect.getRelationship(p));
|
||||||
// Next easiest: Some endpoints of the rectangle are inside, and some are outside.
|
// 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));
|
assertEquals(GeoArea.OVERLAPS, rect.getRelationship(p));
|
||||||
// Now, all points are outside, but the figures intersect
|
// 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));
|
assertEquals(GeoArea.OVERLAPS, rect.getRelationship(p));
|
||||||
// Finally, all points are outside, and the figures *do not* intersect
|
// 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));
|
assertEquals(GeoArea.WITHIN, rect.getRelationship(p));
|
||||||
// Check that segment edge overlap detection works
|
// 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));
|
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));
|
assertEquals(GeoArea.DISJOINT, rect.getRelationship(p));
|
||||||
// Check if overlap at endpoints behaves as expected next
|
// 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));
|
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));
|
assertEquals(GeoArea.DISJOINT, rect.getRelationship(p));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -165,7 +166,7 @@ public class GeoPathTest {
|
||||||
GeoPath c;
|
GeoPath c;
|
||||||
Bounds b;
|
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.addPoint(0.3, 0.3);
|
c.addPoint(0.3, 0.3);
|
||||||
c.done();
|
c.done();
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
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 com.spatial4j.core.distance.DistanceUtils;
|
||||||
|
import org.apache.lucene.util.LuceneTestCase;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomFloat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test basic GeoPoint functionality.
|
||||||
|
*/
|
||||||
|
public class GeoPointTest extends LuceneTestCase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConversion() {
|
||||||
|
testPointRoundTrip(PlanetModel.SPHERE, 90, 0, 1e-12);
|
||||||
|
testPointRoundTrip(PlanetModel.SPHERE, -90, 0, 1e-12);
|
||||||
|
testPointRoundTrip(PlanetModel.WGS84, 90, 0, 1e-12);
|
||||||
|
testPointRoundTrip(PlanetModel.WGS84, -90, 0, 1e-12);
|
||||||
|
|
||||||
|
final int times = atLeast(100);
|
||||||
|
for (int i = 0; i < times; i++) {
|
||||||
|
final double pLat = (randomFloat() * 180.0 - 90.0) * DistanceUtils.DEGREES_TO_RADIANS;
|
||||||
|
final double pLon = (randomFloat() * 360.0 - 180.0) * DistanceUtils.DEGREES_TO_RADIANS;
|
||||||
|
testPointRoundTrip(PlanetModel.SPHERE, pLat, pLon, 1e-6);//1e-6 since there's a square root in there (Karl says)
|
||||||
|
testPointRoundTrip(PlanetModel.WGS84, pLat, pLon, 1e-6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void testPointRoundTrip(PlanetModel planetModel, double pLat, double pLon, double epsilon) {
|
||||||
|
final GeoPoint p1 = new GeoPoint(planetModel, pLat, pLon);
|
||||||
|
final GeoPoint p2 = new GeoPoint(planetModel, p1.getLatitude(), p1.getLongitude());
|
||||||
|
double dist = p1.arcDistance(p2);
|
||||||
|
assertEquals(0, dist, epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,49 +36,49 @@ public class GeoPolygonTest {
|
||||||
List<GeoPoint> points;
|
List<GeoPoint> points;
|
||||||
|
|
||||||
points = new ArrayList<GeoPoint>();
|
points = new ArrayList<GeoPoint>();
|
||||||
points.add(new GeoPoint(-0.1, -0.5));
|
points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.5));
|
||||||
points.add(new GeoPoint(0.0, -0.6));
|
points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.6));
|
||||||
points.add(new GeoPoint(0.1, -0.5));
|
points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.5));
|
||||||
points.add(new GeoPoint(0.0, -0.4));
|
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
|
// Sample some points within
|
||||||
gp = new GeoPoint(0.0, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, -0.55);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, -0.45);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
gp = new GeoPoint(-0.05, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.05, -0.5);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.05, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.05, -0.5);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
// Sample some nearby points outside
|
// 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));
|
assertFalse(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, -0.35);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.35);
|
||||||
assertFalse(c.isWithin(gp));
|
assertFalse(c.isWithin(gp));
|
||||||
gp = new GeoPoint(-0.15, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.15, -0.5);
|
||||||
assertFalse(c.isWithin(gp));
|
assertFalse(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.15, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.15, -0.5);
|
||||||
assertFalse(c.isWithin(gp));
|
assertFalse(c.isWithin(gp));
|
||||||
// Random points outside
|
// Random points outside
|
||||||
gp = new GeoPoint(0.0, 0.0);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
|
||||||
assertFalse(c.isWithin(gp));
|
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));
|
assertFalse(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, Math.PI);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
|
||||||
assertFalse(c.isWithin(gp));
|
assertFalse(c.isWithin(gp));
|
||||||
|
|
||||||
points = new ArrayList<GeoPoint>();
|
points = new ArrayList<GeoPoint>();
|
||||||
points.add(new GeoPoint(-0.1, -0.5));
|
points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.5));
|
||||||
points.add(new GeoPoint(-0.01, -0.6));
|
points.add(new GeoPoint(PlanetModel.SPHERE, -0.01, -0.6));
|
||||||
points.add(new GeoPoint(-0.1, -0.7));
|
points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.7));
|
||||||
points.add(new GeoPoint(0.0, -0.8));
|
points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.8));
|
||||||
points.add(new GeoPoint(0.1, -0.7));
|
points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.7));
|
||||||
points.add(new GeoPoint(0.01, -0.6));
|
points.add(new GeoPoint(PlanetModel.SPHERE, 0.01, -0.6));
|
||||||
points.add(new GeoPoint(0.1, -0.5));
|
points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.5));
|
||||||
points.add(new GeoPoint(0.0, -0.4));
|
points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.4));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
System.out.println("Points: ");
|
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
|
// Sample some points within
|
||||||
gp = new GeoPoint(0.0, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.5);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, -0.55);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.55);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, -0.45);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.45);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
gp = new GeoPoint(-0.05, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.05, -0.5);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.05, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.05, -0.5);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, -0.7);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, -0.7);
|
||||||
assertTrue(c.isWithin(gp));
|
assertTrue(c.isWithin(gp));
|
||||||
// Sample some nearby points outside
|
// 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));
|
assertFalse(c.isWithin(gp));
|
||||||
gp = new GeoPoint(-0.15, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, -0.15, -0.5);
|
||||||
assertFalse(c.isWithin(gp));
|
assertFalse(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.15, -0.5);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.15, -0.5);
|
||||||
assertFalse(c.isWithin(gp));
|
assertFalse(c.isWithin(gp));
|
||||||
// Random points outside
|
// Random points outside
|
||||||
gp = new GeoPoint(0.0, 0.0);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, 0.0);
|
||||||
assertFalse(c.isWithin(gp));
|
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));
|
assertFalse(c.isWithin(gp));
|
||||||
gp = new GeoPoint(0.0, Math.PI);
|
gp = new GeoPoint(PlanetModel.SPHERE, 0.0, Math.PI);
|
||||||
assertFalse(c.isWithin(gp));
|
assertFalse(c.isWithin(gp));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -125,12 +125,12 @@ public class GeoPolygonTest {
|
||||||
List<GeoPoint> points;
|
List<GeoPoint> points;
|
||||||
|
|
||||||
points = new ArrayList<GeoPoint>();
|
points = new ArrayList<GeoPoint>();
|
||||||
points.add(new GeoPoint(-0.1, -0.5));
|
points.add(new GeoPoint(PlanetModel.SPHERE, -0.1, -0.5));
|
||||||
points.add(new GeoPoint(0.0, -0.6));
|
points.add(new GeoPoint(PlanetModel.SPHERE, 0.0, -0.6));
|
||||||
points.add(new GeoPoint(0.1, -0.5));
|
points.add(new GeoPoint(PlanetModel.SPHERE, 0.1, -0.5));
|
||||||
points.add(new GeoPoint(0.0, -0.4));
|
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);
|
b = c.getBounds(null);
|
||||||
assertFalse(b.checkNoLongitudeBound());
|
assertFalse(b.checkNoLongitudeBound());
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class PlaneTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIdenticalPlanes() {
|
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 plane1 = new Plane(p, 0.0);
|
||||||
final Plane plane2 = new Plane(p, 0.0);
|
final Plane plane2 = new Plane(p, 0.0);
|
||||||
assertTrue(plane1.isNumericallyIdentical(plane2));
|
assertTrue(plane1.isNumericallyIdentical(plane2));
|
||||||
|
|
Loading…
Reference in New Issue