LUCENE-3795: re-optimize degrees-radians conversions

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1300457 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yonik Seeley 2012-03-14 04:05:51 +00:00
parent 8854531251
commit d8fff9b873
5 changed files with 24 additions and 20 deletions

View File

@ -36,6 +36,7 @@ import org.apache.lucene.util.Bits;
import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException;
import org.apache.solr.response.TextResponseWriter; import org.apache.solr.response.TextResponseWriter;
import org.apache.solr.search.*; import org.apache.solr.search.*;
import org.apache.solr.search.function.distance.HaversineConstFunction;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -49,7 +50,7 @@ import java.util.Set;
*/ */
public class LatLonType extends AbstractSubTypeFieldType implements SpatialQueryable { public class LatLonType extends AbstractSubTypeFieldType implements SpatialQueryable {
protected static final int LAT = 0; protected static final int LAT = 0;
protected static final int LONG = 1; protected static final int LON = 1;
@Override @Override
protected void init(IndexSchema schema, Map<String, String> args) { protected void init(IndexSchema schema, Map<String, String> args) {
@ -75,7 +76,7 @@ public class LatLonType extends AbstractSubTypeFieldType implements SpatialQuery
f[i] = subField(field, i).createField(String.valueOf(latLon[LAT]), boost); f[i] = subField(field, i).createField(String.valueOf(latLon[LAT]), boost);
i++; i++;
//longitude //longitude
f[i] = subField(field, i).createField(String.valueOf(latLon[LONG]), boost); f[i] = subField(field, i).createField(String.valueOf(latLon[LON]), boost);
} }
@ -142,7 +143,7 @@ public class LatLonType extends AbstractSubTypeFieldType implements SpatialQuery
// lat & lon in degrees // lat & lon in degrees
double latCenter = point[LAT]; double latCenter = point[LAT];
double lonCenter = point[LONG]; double lonCenter = point[LON];
DistanceCalculator distCalc = new GeodesicSphereDistCalc.Haversine(options.units.earthRadius()); DistanceCalculator distCalc = new GeodesicSphereDistCalc.Haversine(options.units.earthRadius());
SpatialContext ctx = new SimpleSpatialContext(options.units,distCalc,null); SpatialContext ctx = new SimpleSpatialContext(options.units,distCalc,null);
@ -164,7 +165,7 @@ public class LatLonType extends AbstractSubTypeFieldType implements SpatialQuery
// Now that we've figured out the ranges, build them! // Now that we've figured out the ranges, build them!
SchemaField latField = subField(options.field, LAT); SchemaField latField = subField(options.field, LAT);
SchemaField lonField = subField(options.field, LONG); SchemaField lonField = subField(options.field, LON);
SpatialDistanceQuery spatial = new SpatialDistanceQuery(); SpatialDistanceQuery spatial = new SpatialDistanceQuery();
@ -398,8 +399,8 @@ class SpatialDistanceQuery extends ExtendedQueryBase implements PostFilter {
this.lon2 = SpatialDistanceQuery.this.lon2; this.lon2 = SpatialDistanceQuery.this.lon2;
this.calcDist = SpatialDistanceQuery.this.calcDist; this.calcDist = SpatialDistanceQuery.this.calcDist;
this.latCenterRad = Math.toRadians(SpatialDistanceQuery.this.latCenter); this.latCenterRad = SpatialDistanceQuery.this.latCenter * HaversineConstFunction.DEGREES_TO_RADIANS;
this.lonCenterRad = Math.toRadians(SpatialDistanceQuery.this.lonCenter); this.lonCenterRad = SpatialDistanceQuery.this.lonCenter * HaversineConstFunction.DEGREES_TO_RADIANS;
this.latCenterRad_cos = this.calcDist ? Math.cos(latCenterRad) : 0; this.latCenterRad_cos = this.calcDist ? Math.cos(latCenterRad) : 0;
this.dist = SpatialDistanceQuery.this.dist; this.dist = SpatialDistanceQuery.this.dist;
this.planetRadius = SpatialDistanceQuery.this.planetRadius; this.planetRadius = SpatialDistanceQuery.this.planetRadius;
@ -428,8 +429,8 @@ class SpatialDistanceQuery extends ExtendedQueryBase implements PostFilter {
} }
double dist(double lat, double lon) { double dist(double lat, double lon) {
double latRad = Math.toRadians(lat); double latRad = lat * HaversineConstFunction.DEGREES_TO_RADIANS;
double lonRad = Math.toRadians(lon); double lonRad = lon * HaversineConstFunction.DEGREES_TO_RADIANS;
// haversine, specialized to avoid a cos() call on latCenterRad // haversine, specialized to avoid a cos() call on latCenterRad
double diffX = latCenterRad - latRad; double diffX = latCenterRad - latRad;

View File

@ -362,13 +362,13 @@ public abstract class ValueSourceParser implements NamedListInitializedPlugin {
addParser(new DoubleParser("rad") { addParser(new DoubleParser("rad") {
@Override @Override
public double func(int doc, FunctionValues vals) { public double func(int doc, FunctionValues vals) {
return Math.toRadians(vals.doubleVal(doc)); return vals.doubleVal(doc) * HaversineConstFunction.DEGREES_TO_RADIANS;
} }
}); });
addParser(new DoubleParser("deg") { addParser(new DoubleParser("deg") {
@Override @Override
public double func(int doc, FunctionValues vals) { public double func(int doc, FunctionValues vals) {
return Math.toDegrees(vals.doubleVal(doc)); return vals.doubleVal(doc) * HaversineConstFunction.RADIANS_TO_DEGREES;
} }
}); });
addParser(new DoubleParser("sqrt") { addParser(new DoubleParser("sqrt") {

View File

@ -44,6 +44,9 @@ import java.util.Map;
* Haversine function with one point constant * Haversine function with one point constant
*/ */
public class HaversineConstFunction extends ValueSource { public class HaversineConstFunction extends ValueSource {
// TODO: these could go in spatial4j somewhere
public static final double DEGREES_TO_RADIANS = Math.PI / 180.0;
public static final double RADIANS_TO_DEGREES = 180.0 / Math.PI;
public static ValueSourceParser parser = new ValueSourceParser() { public static ValueSourceParser parser = new ValueSourceParser() {
@Override @Override
@ -190,7 +193,7 @@ public class HaversineConstFunction extends ValueSource {
this.p2 = vs; this.p2 = vs;
this.latSource = p2.getSources().get(0); this.latSource = p2.getSources().get(0);
this.lonSource = p2.getSources().get(1); this.lonSource = p2.getSources().get(1);
this.latCenterRad_cos = Math.cos(Math.toRadians(latCenter)); this.latCenterRad_cos = Math.cos(latCenter * DEGREES_TO_RADIANS);
} }
protected String name() { protected String name() {
@ -201,15 +204,15 @@ public class HaversineConstFunction extends ValueSource {
public FunctionValues getValues(Map context, AtomicReaderContext readerContext) throws IOException { public FunctionValues getValues(Map context, AtomicReaderContext readerContext) throws IOException {
final FunctionValues latVals = latSource.getValues(context, readerContext); final FunctionValues latVals = latSource.getValues(context, readerContext);
final FunctionValues lonVals = lonSource.getValues(context, readerContext); final FunctionValues lonVals = lonSource.getValues(context, readerContext);
final double latCenterRad = Math.toRadians(this.latCenter); final double latCenterRad = this.latCenter * DEGREES_TO_RADIANS;
final double lonCenterRad = Math.toRadians(this.lonCenter); final double lonCenterRad = this.lonCenter * DEGREES_TO_RADIANS;
final double latCenterRad_cos = this.latCenterRad_cos; final double latCenterRad_cos = this.latCenterRad_cos;
return new DoubleDocValues(this) { return new DoubleDocValues(this) {
@Override @Override
public double doubleVal(int doc) { public double doubleVal(int doc) {
double latRad = Math.toRadians(latVals.doubleVal(doc)); double latRad = latVals.doubleVal(doc) * DEGREES_TO_RADIANS;
double lonRad = Math.toRadians(lonVals.doubleVal(doc)); double lonRad = lonVals.doubleVal(doc) * DEGREES_TO_RADIANS;
double diffX = latCenterRad - latRad; double diffX = latCenterRad - latRad;
double diffY = lonCenterRad - lonRad; double diffY = lonCenterRad - lonRad;
double hsinX = Math.sin(diffX * 0.5); double hsinX = Math.sin(diffX * 0.5);

View File

@ -81,10 +81,10 @@ public class HaversineFunction extends ValueSource {
double y2; double y2;
double x2; double x2;
if (convertToRadians) { if (convertToRadians) {
y1 = Math.toRadians(p1D[0]); y1 = p1D[0] * HaversineConstFunction.DEGREES_TO_RADIANS;
x1 = Math.toRadians(p1D[1]); x1 = p1D[1] * HaversineConstFunction.DEGREES_TO_RADIANS;
y2 = Math.toRadians(p2D[0]); y2 = p2D[0] * HaversineConstFunction.DEGREES_TO_RADIANS;
x2 = Math.toRadians(p2D[1]); x2 = p2D[1] * HaversineConstFunction.DEGREES_TO_RADIANS;
} else { } else {
y1 = p1D[0]; y1 = p1D[0];
x1 = p1D[1]; x1 = p1D[1];

View File

@ -169,7 +169,7 @@ public class SpatialFilterTest extends SolrTestCaseJ4 {
assertQ(req("fl", "id", "q","*:* OR foo_i:" + random.nextInt(100)+100, "rows", "1000", "fq", "{!"+method+" sfield=" +fieldName + " cache=false cost=150" + "}", assertQ(req("fl", "id", "q","*:* OR foo_i:" + random.nextInt(100)+100, "rows", "1000", "fq", "{!"+method+" sfield=" +fieldName + " cache=false cost=150" + "}",
"pt", pt, "d", String.valueOf(distance)), "pt", pt, "d", String.valueOf(distance)),
tests); tests);
assertEquals(postFilterCount + 1, DelegatingCollector.setLastDelegateCount); // post filtering shouldn't be used assertEquals(postFilterCount + 1, DelegatingCollector.setLastDelegateCount); // post filtering *should* have been used
} }
} }