diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index b1517b9dbc2..48117466f73 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -80,6 +80,11 @@ Changes in backwards compatibility policy
can use OrdinalPolicy.NO_PARENTS to never write any parent category ordinal
to the fulltree posting payload (but note that you need a special
FacetsAccumulator - see javadocs). (Shai Erera)
+
+* LUCENE-4594: Spatial PrefixTreeStrategy no longer indexes center points of
+ non-point shapes. If you want to call makeDistanceValueSource() based on
+ shape centers, you need to do this yourself in another spatial field.
+ (David Smiley)
New Features
@@ -246,6 +251,13 @@ Bug Fixes
* LUCENE-4596: fix a concurrency bug in DirectoryTaxonomyWriter.
(Shai Erera)
+* LUCENE-4594: Spatial PrefixTreeStrategy would index center-points in addition
+ to the shape to index if it was non-point, in the same field. But sometimes
+ the center-point isn't actually in the shape (consider a LineString), and for
+ highly precise shapes it could cause makeDistanceValueSource's cache to load
+ parts of the shape's boundary erroneously too. So center points aren't
+ indexed any more; you should use another spatial field. (David Smiley)
+
Changes in Runtime Behavior
* LUCENE-4586: Change default ResultMode of FacetRequest to PER_NODE_IN_TREE.
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/prefix/PrefixTreeStrategy.java b/lucene/spatial/src/java/org/apache/lucene/spatial/prefix/PrefixTreeStrategy.java
index 60525604dee..80073ebe047 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/prefix/PrefixTreeStrategy.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/prefix/PrefixTreeStrategy.java
@@ -45,7 +45,7 @@ import java.util.concurrent.ConcurrentHashMap;
*
Characteristics:
*
* - Can index any shape; however only {@link RecursivePrefixTreeStrategy}
- * can effectively search non-point shapes. Not tested.
+ * can effectively search non-point shapes.
* - Can index a variable number of shapes per field value. This strategy
* can do it via multiple calls to {@link #createIndexableFields(com.spatial4j.core.shape.Shape)}
* for a document or by giving it some sort of Shape aggregate (e.g. JTS
@@ -57,8 +57,9 @@ import java.util.concurrent.ConcurrentHashMap;
* is supported. If only points are indexed then this is effectively equivalent
* to IsWithin.
* - The strategy supports {@link #makeDistanceValueSource(com.spatial4j.core.shape.Point)}
- * even for multi-valued data. However, it will likely be removed in the
- * future in lieu of using another strategy with a more scalable
+ * 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
* implementation. Use of this call is the only
* circumstance in which a cache is used. The cache is simple but as such
* it doesn't scale to large numbers of points nor is it real-time-search
@@ -123,20 +124,12 @@ public abstract class PrefixTreeStrategy extends SpatialStrategy {
public Field[] createIndexableFields(Shape shape, double distErr) {
int detailLevel = grid.getLevelForDistance(distErr);
List cells = grid.getNodes(shape, detailLevel, true);//true=intermediates cells
- //If shape isn't a point, add a full-resolution center-point so that
- // PointPrefixTreeFieldCacheProvider has the center-points.
- //TODO index each point of a multi-point or other aggregate.
- //TODO remove this once support for a distance ValueSource is removed.
- if (!(shape instanceof Point)) {
- Point ctr = shape.getCenter();
- //TODO should be smarter; don't index 2 tokens for this in CellTokenStream. Harmless though.
- cells.add(grid.getNodes(ctr,grid.getMaxLevels(),false).get(0));
- }
//TODO is CellTokenStream supposed to be re-used somehow? see Uwe's comments:
// http://code.google.com/p/lucene-spatial-playground/issues/detail?id=4
- Field field = new Field(getFieldName(), new CellTokenStream(cells.iterator()), FIELD_TYPE);
+ Field field = new Field(getFieldName(),
+ new CellTokenStream(cells.iterator()), FIELD_TYPE);
return new Field[]{field};
}