Index: lucene/spatial/src/test/org/apache/lucene/spatial/SpatialExample.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/test/org/apache/lucene/spatial/SpatialExample.java (revision 1503302)
+++ lucene/spatial/src/test/org/apache/lucene/spatial/SpatialExample.java (revision )
@@ -162,7 +162,8 @@
//--Match all, order by distance ascending
{
Point pt = ctx.makePoint(60, -50);
- ValueSource valueSource = strategy.makeDistanceValueSource(pt);//the distance (in degrees)
+ double degToKm = DistanceUtils.degrees2Dist(1, DistanceUtils.EARTH_MEAN_RADIUS_KM);
+ ValueSource valueSource = strategy.makeDistanceValueSource(pt, degToKm);//the distance (in km)
Sort distSort = new Sort(valueSource.getSortField(false)).rewrite(indexSearcher);//false=asc dist
TopDocs docs = indexSearcher.search(new MatchAllDocsQuery(), 10, distSort);
assertDocMatchedIds(indexSearcher, docs, 4, 20, 2);
Index: lucene/spatial/src/java/org/apache/lucene/spatial/vector/PointVectorStrategy.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/java/org/apache/lucene/spatial/vector/PointVectorStrategy.java (revision 1503302)
+++ lucene/spatial/src/java/org/apache/lucene/spatial/vector/PointVectorStrategy.java (revision )
@@ -120,8 +120,8 @@
}
@Override
- public ValueSource makeDistanceValueSource(Point queryPoint) {
- return new DistanceValueSource(this, queryPoint);
+ public ValueSource makeDistanceValueSource(Point queryPoint, double multiplier) {
+ return new DistanceValueSource(this, queryPoint, multiplier);
}
@Override
Index: solr/core/src/java/org/apache/solr/schema/AbstractSpatialFieldType.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- solr/core/src/java/org/apache/solr/schema/AbstractSpatialFieldType.java (revision 1503302)
+++ solr/core/src/java/org/apache/solr/schema/AbstractSpatialFieldType.java (revision )
@@ -240,12 +240,14 @@
//We get the valueSource for the score then the filter and combine them.
ValueSource valueSource;
- if ("distance".equals(score))
- valueSource = strategy.makeDistanceValueSource(spatialArgs.getShape().getCenter());
- else if ("recipDistance".equals(score))
+ if ("distance".equals(score)) {
+ double multiplier = 1.0;//TODO support units=kilometers
+ valueSource = strategy.makeDistanceValueSource(spatialArgs.getShape().getCenter(), multiplier);
+ } else if ("recipDistance".equals(score)) {
valueSource = strategy.makeRecipDistanceValueSource(spatialArgs.getShape());
- else
+ } else {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "'score' local-param must be one of 'none', 'distance', or 'recipDistance'");
+ }
FunctionQuery functionQuery = new FunctionQuery(valueSource);
if (localParams != null && !localParams.getBool(FILTER_PARAM, true))
Index: lucene/spatial/src/test/org/apache/lucene/spatial/DistanceStrategyTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/test/org/apache/lucene/spatial/DistanceStrategyTest.java (revision 1503302)
+++ lucene/spatial/src/test/org/apache/lucene/spatial/DistanceStrategyTest.java (revision )
@@ -34,6 +34,7 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
public class DistanceStrategyTest extends StrategyTestCase {
@@ -121,6 +122,11 @@
void checkDistValueSource(String ptStr, float... distances) throws IOException {
Point pt = (Point) ctx.readShape(ptStr);
- checkValueSource(strategy.makeDistanceValueSource(pt), distances, 1.0e-4f);
+ float multiplier = random().nextFloat() * 100f;
+ float[] dists2 = Arrays.copyOf(distances, distances.length);
+ for (int i = 0; i < dists2.length; i++) {
+ dists2[i] *= multiplier;
+ }
+ checkValueSource(strategy.makeDistanceValueSource(pt, multiplier), dists2, 1.0e-3f);
}
}
Index: lucene/spatial/src/java/org/apache/lucene/spatial/prefix/PrefixTreeStrategy.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/java/org/apache/lucene/spatial/prefix/PrefixTreeStrategy.java (revision 1503302)
+++ lucene/spatial/src/java/org/apache/lucene/spatial/prefix/PrefixTreeStrategy.java (revision )
@@ -56,7 +56,7 @@
*
Only {@link org.apache.lucene.spatial.query.SpatialOperation#Intersects}
* is supported. If only points are indexed then this is effectively equivalent
* to IsWithin.
- * The strategy supports {@link #makeDistanceValueSource(com.spatial4j.core.shape.Point)}
+ * The strategy supports {@link #makeDistanceValueSource(com.spatial4j.core.shape.Point,double)}
* even for multi-valued data, so long as the indexed data is all points; the
* behavior is undefined otherwise. However, it will likely be removed in
* the future in lieu of using another strategy with a more scalable
@@ -182,7 +182,7 @@
}
@Override
- public ValueSource makeDistanceValueSource(Point queryPoint) {
+ public ValueSource makeDistanceValueSource(Point queryPoint, double multiplier) {
PointPrefixTreeFieldCacheProvider p = provider.get( getFieldName() );
if( p == null ) {
synchronized (this) {//double checked locking idiom is okay since provider is threadsafe
@@ -194,7 +194,7 @@
}
}
- return new ShapeFieldCacheDistanceValueSource(ctx, p, queryPoint);
+ return new ShapeFieldCacheDistanceValueSource(ctx, p, queryPoint, multiplier);
}
public SpatialPrefixTree getGrid() {
Index: lucene/spatial/src/java/org/apache/lucene/spatial/SpatialStrategy.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/java/org/apache/lucene/spatial/SpatialStrategy.java (revision 1503302)
+++ lucene/spatial/src/java/org/apache/lucene/spatial/SpatialStrategy.java (revision )
@@ -102,11 +102,20 @@
public abstract Field[] createIndexableFields(Shape shape);
/**
+ * See {@link #makeDistanceValueSource(com.spatial4j.core.shape.Point, double)} called with
+ * a multiplier of 1.0 (i.e. units of degrees).
+ */
+ public ValueSource makeDistanceValueSource(Point queryPoint) {
+ return makeDistanceValueSource(queryPoint, 1.0);
+ }
+
+ /**
* Make a ValueSource returning the distance between the center of the
* indexed shape and {@code queryPoint}. If there are multiple indexed shapes
- * then the closest one is chosen.
+ * then the closest one is chosen. The result is multiplied by {@code multiplier}, which
+ * conveniently is used to get the desired units.
*/
- public abstract ValueSource makeDistanceValueSource(Point queryPoint);
+ public abstract ValueSource makeDistanceValueSource(Point queryPoint, double multiplier);
/**
* Make a Query based principally on {@link org.apache.lucene.spatial.query.SpatialOperation}
@@ -139,7 +148,7 @@
/**
* Returns a ValueSource with values ranging from 1 to 0, depending inversely
- * on the distance from {@link #makeDistanceValueSource(com.spatial4j.core.shape.Point)}.
+ * on the distance from {@link #makeDistanceValueSource(com.spatial4j.core.shape.Point,double)}.
* The formula is {@code c/(d + c)} where 'd' is the distance and 'c' is
* one tenth the distance to the farthest edge from the center. Thus the
* scores will be 1 for indexed points at the center of the query shape and as
@@ -151,7 +160,7 @@
ctx.makePoint(bbox.getMinX(), bbox.getMinY()), bbox.getMaxX(), bbox.getMaxY());
double distToEdge = diagonalDist * 0.5;
float c = (float)distToEdge * 0.1f;//one tenth
- return new ReciprocalFloatFunction(makeDistanceValueSource(queryShape.getCenter()), 1f, c, c);
+ return new ReciprocalFloatFunction(makeDistanceValueSource(queryShape.getCenter(), 1.0), 1f, c, c);
}
@Override
Index: lucene/spatial/src/java/org/apache/lucene/spatial/bbox/DistanceSimilarity.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/java/org/apache/lucene/spatial/bbox/DistanceSimilarity.java (revision 1503302)
+++ lucene/spatial/src/java/org/apache/lucene/spatial/bbox/DistanceSimilarity.java (revision )
@@ -30,13 +30,15 @@
*/
public class DistanceSimilarity implements BBoxSimilarity {
private final Point queryPoint;
+ private final double multiplier;
private final DistanceCalculator distCalc;
private final double nullValue;
- public DistanceSimilarity(SpatialContext ctx, Point queryPoint) {
+ public DistanceSimilarity(SpatialContext ctx, Point queryPoint, double multiplier) {
this.queryPoint = queryPoint;
+ this.multiplier = multiplier;
this.distCalc = ctx.getDistCalc();
- this.nullValue = (ctx.isGeo() ? 180 : Double.MAX_VALUE);
+ this.nullValue = (ctx.isGeo() ? 180 * multiplier : Double.MAX_VALUE);
}
@Override
@@ -45,14 +47,43 @@
if (indexRect == null) {
score = nullValue;
} else {
- score = distCalc.distance(queryPoint, indexRect.getCenter());
+ score = distCalc.distance(queryPoint, indexRect.getCenter()) * multiplier;
}
if (exp != null) {
exp.setValue((float)score);
exp.setDescription(this.getClass().getSimpleName());
- exp.addDetail(new Explanation(-1f,""+queryPoint));
+ exp.addDetail(new Explanation(-1f, "" + queryPoint));
exp.addDetail(new Explanation(-1f,""+indexRect));
+ exp.addDetail(new Explanation((float)multiplier,"multiplier"));
}
return score;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ DistanceSimilarity that = (DistanceSimilarity) o;
+
+ if (Double.compare(that.multiplier, multiplier) != 0) return false;
+ if (Double.compare(that.nullValue, nullValue) != 0) return false;
+ if (!distCalc.equals(that.distCalc)) return false;
+ if (!queryPoint.equals(that.queryPoint)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result;
+ long temp;
+ result = queryPoint.hashCode();
+ temp = Double.doubleToLongBits(multiplier);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ result = 31 * result + distCalc.hashCode();
+ temp = Double.doubleToLongBits(nullValue);
+ result = 31 * result + (int) (temp ^ (temp >>> 32));
+ return result;
}
}
Index: lucene/spatial/src/java/org/apache/lucene/spatial/vector/DistanceValueSource.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/java/org/apache/lucene/spatial/vector/DistanceValueSource.java (revision 1503302)
+++ lucene/spatial/src/java/org/apache/lucene/spatial/vector/DistanceValueSource.java (revision )
@@ -39,13 +39,15 @@
private PointVectorStrategy strategy;
private final Point from;
+ private final double multiplier;
/**
* Constructor.
*/
- public DistanceValueSource(PointVectorStrategy strategy, Point from) {
+ public DistanceValueSource(PointVectorStrategy strategy, Point from, double multiplier) {
this.strategy = strategy;
this.from = from;
+ this.multiplier = multiplier;
}
/**
@@ -72,7 +74,8 @@
private final Point from = DistanceValueSource.this.from;
private final DistanceCalculator calculator = strategy.getSpatialContext().getDistCalc();
- private final double nullValue = (strategy.getSpatialContext().isGeo() ? 180 : Double.MAX_VALUE);
+ private final double nullValue =
+ (strategy.getSpatialContext().isGeo() ? 180 * multiplier : Double.MAX_VALUE);
@Override
public float floatVal(int doc) {
@@ -84,7 +87,7 @@
// make sure it has minX and area
if (validX.get(doc)) {
assert validY.get(doc);
- return calculator.distance(from, ptX.get(doc), ptY.get(doc));
+ return calculator.distance(from, ptX.get(doc), ptY.get(doc)) * multiplier;
}
return nullValue;
}
@@ -105,6 +108,7 @@
if (!from.equals(that.from)) return false;
if (!strategy.equals(that.strategy)) return false;
+ if (multiplier != that.multiplier) return false;
return true;
}
Index: lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxStrategy.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxStrategy.java (revision 1503302)
+++ lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxStrategy.java (revision )
@@ -135,9 +135,9 @@
//---------------------------------
@Override
- public ValueSource makeDistanceValueSource(Point queryPoint) {
+ public ValueSource makeDistanceValueSource(Point queryPoint, double multiplier) {
return new BBoxSimilarityValueSource(
- this, new DistanceSimilarity(this.getSpatialContext(), queryPoint));
+ this, new DistanceSimilarity(this.getSpatialContext(), queryPoint, multiplier));
}
public ValueSource makeBBoxAreaSimilarityValueSource(Rectangle queryBox) {
Index: lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeFieldCacheDistanceValueSource.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeFieldCacheDistanceValueSource.java (revision 1503302)
+++ lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeFieldCacheDistanceValueSource.java (revision )
@@ -38,14 +38,17 @@
*/
public class ShapeFieldCacheDistanceValueSource extends ValueSource {
- private final ShapeFieldCacheProvider provider;
private final SpatialContext ctx;
private final Point from;
+ private final ShapeFieldCacheProvider provider;
+ private final double multiplier;
- public ShapeFieldCacheDistanceValueSource(SpatialContext ctx, ShapeFieldCacheProvider provider, Point from) {
+ public ShapeFieldCacheDistanceValueSource(SpatialContext ctx,
+ ShapeFieldCacheProvider provider, Point from, double multiplier) {
this.ctx = ctx;
this.from = from;
this.provider = provider;
+ this.multiplier = multiplier;
}
@Override
@@ -60,7 +63,7 @@
provider.getCache(readerContext.reader());
private final Point from = ShapeFieldCacheDistanceValueSource.this.from;
private final DistanceCalculator calculator = ctx.getDistCalc();
- private final double nullValue = (ctx.isGeo() ? 180 : Double.MAX_VALUE);
+ private final double nullValue = (ctx.isGeo() ? 180 * multiplier : Double.MAX_VALUE);
@Override
public float floatVal(int doc) {
@@ -69,13 +72,14 @@
@Override
public double doubleVal(int doc) {
+
List vals = cache.getShapes( doc );
if( vals != null ) {
double v = calculator.distance(from, vals.get(0));
for( int i=1; i