mirror of https://github.com/apache/lucene.git
LUCENE-7140: add spatial3d PlanetModel.bisection method
This commit is contained in:
parent
b8feb92271
commit
626bed8bc6
|
@ -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%
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue