LUCENE-7140: add spatial3d PlanetModel.bisection method

This commit is contained in:
Mike McCandless 2016-03-25 08:21:44 -04:00
parent b8feb92271
commit 626bed8bc6
3 changed files with 46 additions and 0 deletions

View File

@ -13,6 +13,9 @@ New Features
* LUCENE-7099: Add LatLonPoint.newDistanceSort to the sandbox's
LatLonPoint. (Robert Muir)
* LUCENE-7140: Add PlanetModel.bisection to spatial3d (Karl Wright via
Mike McCandless)
Optimizations
* LUCENE-7071: Reduce bytes copying in OfflineSorter, giving ~10%

View File

@ -188,6 +188,30 @@ public class PlanetModel {
return (x * x + y * y) * inverseAb * inverseAb + z * z * inverseC * inverseC - 1.0 > Vector.MINIMUM_RESOLUTION;
}
/** Compute a GeoPoint that's a bisection between two other GeoPoints.
* @param pt1 is the first point.
* @param pt2 is the second point.
* @return the bisection point, or null if a unique one cannot be found.
*/
public GeoPoint bisection(final GeoPoint pt1, final GeoPoint pt2) {
final double A0 = (pt1.x + pt2.x) * 0.5;
final double B0 = (pt1.y + pt2.y) * 0.5;
final double C0 = (pt1.z + pt2.z) * 0.5;
final double denom = inverseAbSquared * A0 * A0 +
inverseAbSquared * B0 * B0 +
inverseCSquared * C0 * C0;
if(denom < Vector.MINIMUM_RESOLUTION) {
// Bisection is undefined
return null;
}
final double t = Math.sqrt(1.0 / denom);
return new GeoPoint(t * A0, t * B0, t * C0);
}
/** Compute surface distance between two points.
* @param pt1 is the first point.
* @param pt2 is the second point.

View File

@ -83,6 +83,25 @@ public class GeoPointTest extends LuceneTestCase {
}
}
@Test
public void testBisection() {
final int times = atLeast(100);
for (int i = 0; i < times; i++) {
final double p1Lat = (randomFloat() * 180.0 - 90.0) * DEGREES_TO_RADIANS;
final double p1Lon = (randomFloat() * 360.0 - 180.0) * DEGREES_TO_RADIANS;
final double p2Lat = (randomFloat() * 180.0 - 90.0) * DEGREES_TO_RADIANS;
final double p2Lon = (randomFloat() * 360.0 - 180.0) * DEGREES_TO_RADIANS;
final GeoPoint p1 = new GeoPoint(PlanetModel.WGS84, p1Lat, p1Lon);
final GeoPoint p2 = new GeoPoint(PlanetModel.WGS84, p2Lat, p2Lon);
final GeoPoint pMid = PlanetModel.WGS84.bisection(p1, p2);
if (pMid != null) {
final double arcDistance = p1.arcDistance(p2);
final double sum = pMid.arcDistance(p1) + pMid.arcDistance(p2);
assertEquals(arcDistance, sum, 1e-6);
}
}
}
@Test(expected = IllegalArgumentException.class)
public void testBadLatLon() {
new GeoPoint(PlanetModel.SPHERE, 50.0, 32.2);