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 1380665) +++ lucene/spatial/src/test/org/apache/lucene/spatial/SpatialExample.java (revision ) @@ -18,7 +18,8 @@ */ import com.spatial4j.core.context.SpatialContext; -import com.spatial4j.core.context.simple.SimpleSpatialContext; +import com.spatial4j.core.distance.DistanceUtils; +import com.spatial4j.core.io.ShapeReadWriter; import com.spatial4j.core.shape.Shape; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; @@ -28,7 +29,6 @@ import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; -import org.apache.lucene.index.IndexableField; import org.apache.lucene.queries.function.ValueSource; import org.apache.lucene.search.Filter; import org.apache.lucene.search.IndexSearcher; @@ -87,7 +87,7 @@ protected void init() { //Typical geospatial context with kilometer units. // These can also be constructed from a factory: SpatialContextFactory - this.ctx = SimpleSpatialContext.GEO_KM; + this.ctx = SpatialContext.GEO; int maxLevels = 10;//results in sub-meter precision for geohash //TODO demo lookup by detail distance @@ -110,7 +110,7 @@ //When parsing a string to a shape, the presence of a comma means it's y-x // order (lon, lat) indexWriter.addDocument(newSampleDocument( - 4, ctx.readShape("-50.7693246, 60.9289094"))); + 4, new ShapeReadWriter(ctx).readShape("-50.7693246, 60.9289094"))); indexWriter.addDocument(newSampleDocument( 20, ctx.makePoint(0.1,0.1), ctx.makePoint(0, 0))); @@ -144,7 +144,7 @@ //Search with circle //note: SpatialArgs can be parsed from a string SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects, - ctx.makeCircle(-80.0, 33.0, 200));//200km (since km == ctx.getDistanceUnits + ctx.makeCircle(-80.0, 33.0, DistanceUtils.dist2Degrees(200, DistanceUtils.EARTH_MEAN_RADIUS_KM))); Filter filter = strategy.makeFilter(args); TopDocs docs = indexSearcher.search(new MatchAllDocsQuery(), filter, 10, idSort); assertDocMatchedIds(indexSearcher, docs, 2); @@ -153,7 +153,7 @@ { SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects,//doesn't matter ctx.makePoint(60, -50)); - ValueSource valueSource = strategy.makeValueSource(args);//the distance + ValueSource valueSource = strategy.makeValueSource(args);//the distance (in degrees) Sort reverseDistSort = new Sort(valueSource.getSortField(false)).rewrite(indexSearcher);//true=asc dist TopDocs docs = indexSearcher.search(new MatchAllDocsQuery(), 10, reverseDistSort); assertDocMatchedIds(indexSearcher, docs, 4, 20, 2); @@ -161,8 +161,8 @@ //demo arg parsing { SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects, - ctx.makeCircle(-80.0, 33.0, 200)); - SpatialArgs args2 = new SpatialArgsParser().parse("Intersects(Circle(33,-80 d=200))", ctx); + ctx.makeCircle(-80.0, 33.0, 1)); + SpatialArgs args2 = new SpatialArgsParser().parse("Intersects(Circle(33,-80 d=1))", ctx); assertEquals(args.toString(),args2.toString()); } Index: lucene/spatial/src/test/org/apache/lucene/spatial/vector/TestTwoDoublesStrategy.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/test/org/apache/lucene/spatial/vector/TestTwoDoublesStrategy.java (revision 1380665) +++ lucene/spatial/src/test/org/apache/lucene/spatial/vector/TestTwoDoublesStrategy.java (revision ) @@ -17,12 +17,10 @@ * limitations under the License. */ -import com.spatial4j.core.context.simple.SimpleSpatialContext; +import com.spatial4j.core.context.SpatialContext; import com.spatial4j.core.exception.InvalidShapeException; import com.spatial4j.core.shape.Circle; import com.spatial4j.core.shape.Point; -import com.spatial4j.core.shape.simple.CircleImpl; -import com.spatial4j.core.shape.simple.PointImpl; import org.apache.lucene.search.Query; import org.apache.lucene.spatial.SpatialMatchConcern; import org.apache.lucene.spatial.StrategyTestCase; @@ -39,13 +37,13 @@ @Override public void setUp() throws Exception { super.setUp(); - this.ctx = SimpleSpatialContext.GEO_KM; + this.ctx = SpatialContext.GEO; this.strategy = new TwoDoublesStrategy(ctx, getClass().getSimpleName()); } @Test public void testCircleShapeSupport() { - Circle circle = new CircleImpl(new PointImpl(0, 0), 10, this.ctx); + Circle circle = ctx.makeCircle(ctx.makePoint(0, 0), 10); SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects, circle); Query query = this.strategy.makeQuery(args); @@ -54,7 +52,7 @@ @Test(expected = InvalidShapeException.class) public void testInvalidQueryShape() { - Point point = new PointImpl(0, 0); + Point point = ctx.makePoint(0, 0); SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects, point); this.strategy.makeQuery(args); } Index: lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialOperation.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialOperation.java (revision 1380665) +++ lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialOperation.java (revision ) @@ -17,8 +17,6 @@ * limitations under the License. */ -import com.spatial4j.core.exception.InvalidSpatialArgument; - import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; @@ -71,7 +69,7 @@ op = registry.get(v.toUpperCase(Locale.ROOT)); } if( op == null ) { - throw new InvalidSpatialArgument("Unknown Operation: " + v ); + throw new IllegalArgumentException("Unknown Operation: " + v ); } return op; } Index: lucene/spatial/src/java/org/apache/lucene/spatial/prefix/tree/QuadPrefixTree.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/java/org/apache/lucene/spatial/prefix/tree/QuadPrefixTree.java (revision 1380665) +++ lucene/spatial/src/java/org/apache/lucene/spatial/prefix/tree/QuadPrefixTree.java (revision ) @@ -22,7 +22,6 @@ import com.spatial4j.core.shape.Rectangle; import com.spatial4j.core.shape.Shape; import com.spatial4j.core.shape.SpatialRelation; -import com.spatial4j.core.shape.simple.PointImpl; import java.io.PrintStream; import java.text.NumberFormat; @@ -134,7 +133,7 @@ @Override public Node getNode(Point p, int level) { List cells = new ArrayList(1); - build(xmid, ymid, 0, cells, new StringBuilder(), new PointImpl(p.getX(),p.getY()), level); + build(xmid, ymid, 0, cells, new StringBuilder(), ctx.makePoint(p.getX(),p.getY()), level); return cells.get(0);//note cells could be longer if p on edge } @@ -195,8 +194,8 @@ double h = levelH[level] / 2; int strlen = str.length(); - Rectangle rectangle = ctx.makeRect(cx - w, cx + w, cy - h, cy + h); - SpatialRelation v = shape.relate(rectangle, ctx); + Rectangle rectangle = ctx.makeRectangle(cx - w, cx + w, cy - h, cy + h); + SpatialRelation v = shape.relate(rectangle); if (SpatialRelation.CONTAINS == v) { str.append(c); //str.append(SpatialPrefixGrid.COVER); @@ -297,7 +296,7 @@ width = gridW; height = gridH; } - return ctx.makeRect(xmin, xmin + width, ymin, ymin + height); + return ctx.makeRectangle(xmin, xmin + width, ymin, ymin + height); } }//QuadCell } Index: lucene/spatial/src/java/org/apache/lucene/spatial/bbox/AreaSimilarity.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/java/org/apache/lucene/spatial/bbox/AreaSimilarity.java (revision 1380665) +++ lucene/spatial/src/java/org/apache/lucene/spatial/bbox/AreaSimilarity.java (revision ) @@ -57,7 +57,7 @@ public AreaSimilarity(Rectangle queryExtent, double queryPower, double targetPower) { this.queryExtent = queryExtent; - this.queryArea = queryExtent.getArea(); + this.queryArea = queryExtent.getArea(null); this.queryPower = queryPower; this.targetPower = targetPower; @@ -84,7 +84,7 @@ if (target == null || queryArea <= 0) { return 0; } - double targetArea = target.getArea(); + double targetArea = target.getArea(null); if (targetArea <= 0) { return 0; } Index: lucene/spatial/src/java/org/apache/lucene/spatial/prefix/tree/GeohashPrefixTree.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/java/org/apache/lucene/spatial/prefix/tree/GeohashPrefixTree.java (revision 1380665) +++ lucene/spatial/src/java/org/apache/lucene/spatial/prefix/tree/GeohashPrefixTree.java (revision ) @@ -21,7 +21,7 @@ import com.spatial4j.core.shape.Point; import com.spatial4j.core.shape.Rectangle; import com.spatial4j.core.shape.Shape; -import com.spatial4j.core.util.GeohashUtils; +import com.spatial4j.core.io.GeohashUtils; import java.util.ArrayList; import java.util.Collection; @@ -67,39 +67,8 @@ @Override public int getLevelForDistance(double dist) { - final int level = lookupHashLenForWidthHeight(dist, dist); + final int level = GeohashUtils.lookupHashLenForWidthHeight(dist, dist); return Math.max(Math.min(level, maxLevels), 1); - } - - /* TODO temporarily in-lined GeoHashUtils.lookupHashLenForWidthHeight() is fixed in Spatial4j 0.3 */ - - /** - * Return the longest geohash length that will have a width & height >= specified arguments. - */ - private static int lookupHashLenForWidthHeight(double lonErr, double latErr) { - //loop through hash length arrays from beginning till we find one. - for(int len = 1; len <= GeohashUtils.MAX_PRECISION; len++) { - double latHeight = hashLenToLatHeight[len]; - double lonWidth = hashLenToLonWidth[len]; - if (latHeight < latErr && lonWidth < lonErr) - return len; - } - return GeohashUtils.MAX_PRECISION; - } - - /** See the table at http://en.wikipedia.org/wiki/Geohash */ - private static final double[] hashLenToLatHeight, hashLenToLonWidth; - static { - hashLenToLatHeight = new double[GeohashUtils.MAX_PRECISION +1]; - hashLenToLonWidth = new double[GeohashUtils.MAX_PRECISION +1]; - hashLenToLatHeight[0] = 90*2; - hashLenToLonWidth[0] = 180*2; - boolean even = false; - for(int i = 1; i <= GeohashUtils.MAX_PRECISION; i++) { - hashLenToLatHeight[i] = hashLenToLatHeight[i-1]/(even?8:4); - hashLenToLonWidth[i] = hashLenToLonWidth[i-1]/(even?4:8); - even = ! even; - } } @Override Index: solr/core/src/java/org/apache/solr/search/function/distance/HaversineFunction.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- solr/core/src/java/org/apache/solr/search/function/distance/HaversineFunction.java (revision 1380665) +++ solr/core/src/java/org/apache/solr/search/function/distance/HaversineFunction.java (revision ) @@ -81,10 +81,10 @@ double y2; double x2; if (convertToRadians) { - y1 = p1D[0] * HaversineConstFunction.DEGREES_TO_RADIANS; - x1 = p1D[1] * HaversineConstFunction.DEGREES_TO_RADIANS; - y2 = p2D[0] * HaversineConstFunction.DEGREES_TO_RADIANS; - x2 = p2D[1] * HaversineConstFunction.DEGREES_TO_RADIANS; + y1 = p1D[0] * DistanceUtils.DEGREES_TO_RADIANS; + x1 = p1D[1] * DistanceUtils.DEGREES_TO_RADIANS; + y2 = p2D[0] * DistanceUtils.DEGREES_TO_RADIANS; + x2 = p2D[1] * DistanceUtils.DEGREES_TO_RADIANS; } else { y1 = p1D[0]; x1 = p1D[1]; Index: solr/core/src/java/org/apache/solr/search/SpatialOptions.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- solr/core/src/java/org/apache/solr/search/SpatialOptions.java (revision 1380665) +++ solr/core/src/java/org/apache/solr/search/SpatialOptions.java (revision ) @@ -16,7 +16,6 @@ * limitations under the License. */ -import com.spatial4j.core.distance.DistanceUnits; import org.apache.solr.schema.SchemaField; /** @@ -28,8 +27,7 @@ public double distance; public SchemaField field; public String measStr; - public double radius; - public DistanceUnits units; + public double radius;//(planetRadius) effectively establishes the units /** Just do a "bounding box" - or any other quicker method / shape that * still encompasses all of the points of interest, but may also encompass @@ -40,19 +38,11 @@ public SpatialOptions() { } - public SpatialOptions(String pointStr, double dist, SchemaField sf, String measStr, double radius) { - this(pointStr, dist, sf, measStr, radius, DistanceUnits.MILES); - - } - - - public SpatialOptions(String pointStr, double dist, SchemaField sf, String measStr, double radius, DistanceUnits units) { this.pointStr = pointStr; this.distance = dist; this.field = sf; this.measStr = measStr; this.radius = radius; - this.units = units; } } Index: solr/core/src/java/org/apache/solr/search/SpatialFilterQParser.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- solr/core/src/java/org/apache/solr/search/SpatialFilterQParser.java (revision 1380665) +++ solr/core/src/java/org/apache/solr/search/SpatialFilterQParser.java (revision ) @@ -19,7 +19,6 @@ import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.search.Query; -import com.spatial4j.core.distance.DistanceUnits; import com.spatial4j.core.distance.DistanceUtils; import org.apache.solr.common.SolrException; import org.apache.solr.common.params.SolrParams; @@ -79,7 +78,7 @@ if (type instanceof SpatialQueryable) { double radius = localParams.getDouble(SpatialParams.SPHERE_RADIUS, DistanceUtils.EARTH_MEAN_RADIUS_KM); - SpatialOptions opts = new SpatialOptions(pointStr, dist, sf, measStr, radius, DistanceUnits.KILOMETERS); + SpatialOptions opts = new SpatialOptions(pointStr, dist, sf, measStr, radius); opts.bbox = bbox; result = ((SpatialQueryable)type).createSpatialQuery(this, opts); } else { Index: lucene/spatial/ivy.xml IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/ivy.xml (revision 1380665) +++ lucene/spatial/ivy.xml (revision ) @@ -19,7 +19,7 @@ - + Index: solr/core/ivy.xml IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- solr/core/ivy.xml (revision 1380665) +++ solr/core/ivy.xml (revision ) @@ -34,7 +34,7 @@ - + Index: lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java (revision 1380665) +++ lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java (revision ) @@ -18,7 +18,6 @@ */ import com.spatial4j.core.shape.Rectangle; -import com.spatial4j.core.shape.simple.RectangleImpl; import org.apache.lucene.index.AtomicReader; import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.queries.function.FunctionValues; @@ -74,11 +73,14 @@ final Bits validMaxX = FieldCache.DEFAULT.getDocsWithField(reader, strategy.field_maxX); return new FunctionValues() { + //reused + Rectangle rect = strategy.getSpatialContext().makeRectangle(0,0,0,0); + @Override public float floatVal(int doc) { // make sure it has minX and area if (validMinX.get(doc) && validMaxX.get(doc)) { - Rectangle rect = new RectangleImpl( + rect.reset( minX[doc], maxX[doc], minY[doc], maxY[doc]); return (float) similarity.score(rect, null); @@ -89,7 +91,7 @@ public Explanation explain(int doc) { // make sure it has minX and area if (validMinX.get(doc) && validMaxX.get(doc)) { - Rectangle rect = new RectangleImpl( + rect.reset( minX[doc], maxX[doc], minY[doc], maxY[doc]); Explanation exp = new Explanation(); Index: lucene/spatial/src/test/org/apache/lucene/spatial/bbox/TestBBoxStrategy.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/test/org/apache/lucene/spatial/bbox/TestBBoxStrategy.java (revision 1380665) +++ lucene/spatial/src/test/org/apache/lucene/spatial/bbox/TestBBoxStrategy.java (revision ) @@ -17,7 +17,7 @@ * limitations under the License. */ -import com.spatial4j.core.context.simple.SimpleSpatialContext; +import com.spatial4j.core.context.SpatialContext; import org.apache.lucene.spatial.SpatialMatchConcern; import org.apache.lucene.spatial.StrategyTestCase; import org.junit.Before; @@ -31,7 +31,7 @@ @Override public void setUp() throws Exception { super.setUp(); - this.ctx = SimpleSpatialContext.GEO_KM; + this.ctx = SpatialContext.GEO; this.strategy = new BBoxStrategy(ctx, "bbox"); } Index: lucene/spatial/src/test/org/apache/lucene/spatial/PortedSolr3Test.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/test/org/apache/lucene/spatial/PortedSolr3Test.java (revision 1380665) +++ lucene/spatial/src/test/org/apache/lucene/spatial/PortedSolr3Test.java (revision ) @@ -20,14 +20,14 @@ import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; import com.spatial4j.core.context.SpatialContext; -import com.spatial4j.core.context.simple.SimpleSpatialContext; +import com.spatial4j.core.distance.DistanceUtils; +import com.spatial4j.core.io.ShapeReadWriter; import com.spatial4j.core.shape.Point; import com.spatial4j.core.shape.Shape; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.StoredField; import org.apache.lucene.document.StringField; -import org.apache.lucene.index.IndexableField; import org.apache.lucene.search.FilteredQuery; import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.Query; @@ -55,7 +55,7 @@ public static Iterable parameters() { List ctorArgs = new ArrayList(); - SpatialContext ctx = SimpleSpatialContext.GEO_KM; + SpatialContext ctx = SpatialContext.GEO; SpatialPrefixTree grid; SpatialStrategy strategy; @@ -121,6 +121,7 @@ public void testIntersections() throws Exception { setupDocs(); //Try some edge cases + //NOTE: 2nd arg is distance in kilometers checkHitsCircle("1,1", 175, 3, 5, 6, 7); checkHitsCircle("0,179.8", 200, 2, 8, 9); checkHitsCircle("89.8, 50", 200, 2, 10, 11);//this goes over the north pole @@ -164,11 +165,12 @@ adoc("100","1,2"); adoc("101","4,-1"); commit(); + double km1000inDeg = DistanceUtils.dist2Degrees(1000, DistanceUtils.EARTH_MEAN_RADIUS_KM); //query closer to #100 - checkHitsOrdered("Intersects(Circle(3,4 d=1000))", "101", "100"); + checkHitsOrdered("Intersects(Circle(3,4 d="+km1000inDeg+"))", "101", "100"); //query closer to #101 - checkHitsOrdered("Intersects(Circle(4,0 d=1000))", "100", "101"); + checkHitsOrdered("Intersects(Circle(4,0 d="+km1000inDeg+"))", "100", "101"); } private void checkHitsOrdered(String spatialQ, String... ids) { @@ -186,7 +188,7 @@ //---- these are similar to Solr test methods private void adoc(String idStr, String shapeStr) throws IOException { - Shape shape = ctx.readShape(shapeStr); + Shape shape = new ShapeReadWriter(ctx).readShape(shapeStr); addDocument(newDoc(idStr,shape)); } @@ -202,17 +204,18 @@ return doc; } - private void checkHitsCircle(String ptStr, double dist, int assertNumFound, int... assertIds) { - _checkHits(SpatialOperation.Intersects, ptStr, dist, assertNumFound, assertIds); + private void checkHitsCircle(String ptStr, double distKM, int assertNumFound, int... assertIds) { + _checkHits(SpatialOperation.Intersects, ptStr, distKM, assertNumFound, assertIds); } - private void checkHitsBBox(String ptStr, double dist, int assertNumFound, int... assertIds) { - _checkHits(SpatialOperation.BBoxIntersects, ptStr, dist, assertNumFound, assertIds); + private void checkHitsBBox(String ptStr, double distKM, int assertNumFound, int... assertIds) { + _checkHits(SpatialOperation.BBoxIntersects, ptStr, distKM, assertNumFound, assertIds); } @SuppressWarnings("unchecked") - private void _checkHits(SpatialOperation op, String ptStr, double dist, int assertNumFound, int... assertIds) { - Point pt = (Point) ctx.readShape(ptStr); - Shape shape = ctx.makeCircle(pt,dist); + private void _checkHits(SpatialOperation op, String ptStr, double distKM, int assertNumFound, int... assertIds) { + Point pt = (Point) new ShapeReadWriter(ctx).readShape(ptStr); + double distDEG = DistanceUtils.dist2Degrees(distKM, DistanceUtils.EARTH_MEAN_RADIUS_KM); + Shape shape = ctx.makeCircle(pt, distDEG); SpatialArgs args = new SpatialArgs(op,shape); //args.setDistPrecision(0.025); Index: lucene/spatial/src/java/org/apache/lucene/spatial/prefix/RecursivePrefixTreeFilter.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/java/org/apache/lucene/spatial/prefix/RecursivePrefixTreeFilter.java (revision 1380665) +++ lucene/spatial/src/java/org/apache/lucene/spatial/prefix/RecursivePrefixTreeFilter.java (revision ) @@ -142,7 +142,7 @@ if (termLevel == detailLevel || scanCell.isLeaf()) { //TODO should put more thought into implications of box vs point Shape cShape = termLevel == grid.getMaxLevels() ? scanCell.getCenter() : scanCell.getShape(); - if(queryShape.relate(cShape, grid.getSpatialContext()) == SpatialRelation.DISJOINT) + if(queryShape.relate(cShape) == SpatialRelation.DISJOINT) continue; docsEnum = termsEnum.docs(acceptDocs, docsEnum, 0); Index: solr/core/src/java/org/apache/solr/schema/PointType.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- solr/core/src/java/org/apache/solr/schema/PointType.java (revision 1380665) +++ solr/core/src/java/org/apache/solr/schema/PointType.java (revision ) @@ -20,14 +20,12 @@ import org.apache.lucene.document.FieldType; import org.apache.lucene.queries.function.ValueSource; import org.apache.lucene.queries.function.valuesource.VectorValueSource; -import org.apache.lucene.index.GeneralField; -import org.apache.lucene.index.IndexableField; import org.apache.lucene.index.StorableField; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.SortField; -import com.spatial4j.core.context.ParseUtils; +import com.spatial4j.core.io.ParseUtils; import com.spatial4j.core.distance.DistanceUtils; import com.spatial4j.core.exception.InvalidShapeException; import org.apache.solr.common.SolrException; \ No newline at end of file Index: lucene/spatial/src/test/org/apache/lucene/spatial/prefix/tree/SpatialPrefixTreeTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/test/org/apache/lucene/spatial/prefix/tree/SpatialPrefixTreeTest.java (revision 1380665) +++ lucene/spatial/src/test/org/apache/lucene/spatial/prefix/tree/SpatialPrefixTreeTest.java (revision ) @@ -17,7 +17,7 @@ package org.apache.lucene.spatial.prefix.tree; -import com.spatial4j.core.context.simple.SimpleSpatialContext; +import com.spatial4j.core.context.SpatialContext; import com.spatial4j.core.shape.Rectangle; import com.spatial4j.core.shape.Shape; @@ -28,13 +28,13 @@ public class SpatialPrefixTreeTest extends LuceneTestCase { //TODO plug in others and test them - private SimpleSpatialContext ctx; + private SpatialContext ctx; private SpatialPrefixTree trie; @Before public void setUp() throws Exception { super.setUp(); - ctx = SimpleSpatialContext.GEO_KM; + ctx = SpatialContext.GEO; trie = new GeohashPrefixTree(ctx,4); } Index: lucene/spatial/src/test/org/apache/lucene/spatial/StrategyTestCase.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/test/org/apache/lucene/spatial/StrategyTestCase.java (revision 1380665) +++ lucene/spatial/src/test/org/apache/lucene/spatial/StrategyTestCase.java (revision ) @@ -19,6 +19,7 @@ */ import com.spatial4j.core.context.SpatialContext; +import com.spatial4j.core.io.ShapeReadWriter; import com.spatial4j.core.io.sample.SampleData; import com.spatial4j.core.io.sample.SampleDataReader; import com.spatial4j.core.shape.Shape; @@ -84,7 +85,7 @@ Document document = new Document(); document.add(new StringField("id", data.id, Field.Store.YES)); document.add(new StringField("name", data.name, Field.Store.YES)); - Shape shape = ctx.readShape(data.shape); + Shape shape = new ShapeReadWriter(ctx).readShape(data.shape); for (Field f : strategy.createIndexableFields(shape)) { document.add(f); } @@ -117,7 +118,7 @@ SearchResults got = executeQuery(strategy.makeQuery(q.args), 100); if (storeShape && got.numFound > 0) { //check stored value is there & parses - assertNotNull(ctx.readShape(got.results.get(0).document.get(strategy.getFieldName()))); + assertNotNull(new ShapeReadWriter(ctx).readShape(got.results.get(0).document.get(strategy.getFieldName()))); } if (concern.orderIsImportant) { Iterator ids = q.ids.iterator(); Index: lucene/spatial/src/java/org/apache/lucene/spatial/vector/TwoDoublesStrategy.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/java/org/apache/lucene/spatial/vector/TwoDoublesStrategy.java (revision 1380665) +++ lucene/spatial/src/java/org/apache/lucene/spatial/vector/TwoDoublesStrategy.java (revision ) @@ -113,7 +113,7 @@ ValueSource valueSource = makeValueSource(args); return new ValueSourceFilter( - new QueryWrapperFilter( bbox ), valueSource, 0, circle.getDistance() ); + new QueryWrapperFilter( bbox ), valueSource, 0, circle.getRadius() ); } } return new QueryWrapperFilter( makeQuery(args) ); @@ -155,7 +155,7 @@ valueSource = makeValueSource(args); ValueSourceFilter vsf = new ValueSourceFilter( - new QueryWrapperFilter( spatial ), valueSource, 0, circle.getDistance() ); + new QueryWrapperFilter( spatial ), valueSource, 0, circle.getRadius() ); spatial = new FilteredQuery( new MatchAllDocsQuery(), vsf ); } Index: lucene/spatial/src/test/org/apache/lucene/spatial/prefix/TestTermQueryPrefixGridStrategy.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/test/org/apache/lucene/spatial/prefix/TestTermQueryPrefixGridStrategy.java (revision 1380665) +++ lucene/spatial/src/test/org/apache/lucene/spatial/prefix/TestTermQueryPrefixGridStrategy.java (revision ) @@ -18,14 +18,12 @@ */ import com.spatial4j.core.context.SpatialContext; -import com.spatial4j.core.context.simple.SimpleSpatialContext; +import com.spatial4j.core.context.SpatialContext; import com.spatial4j.core.shape.Shape; -import com.spatial4j.core.shape.simple.PointImpl; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.StoredField; import org.apache.lucene.document.StringField; -import org.apache.lucene.index.IndexableField; import org.apache.lucene.spatial.SpatialTestCase; import org.apache.lucene.spatial.prefix.tree.QuadPrefixTree; import org.apache.lucene.spatial.query.SpatialArgsParser; @@ -39,10 +37,10 @@ @Test public void testNGramPrefixGridLosAngeles() throws IOException { - SpatialContext ctx = SimpleSpatialContext.GEO_KM; + SpatialContext ctx = SpatialContext.GEO; TermQueryPrefixTreeStrategy prefixGridStrategy = new TermQueryPrefixTreeStrategy(new QuadPrefixTree(ctx), "geo"); - Shape point = new PointImpl(-118.243680, 34.052230); + Shape point = ctx.makePoint(-118.243680, 34.052230); Document losAngeles = new Document(); losAngeles.add(new StringField("name", "Los Angeles", Field.Store.YES)); Index: solr/core/src/java/org/apache/solr/search/function/distance/HaversineConstFunction.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- solr/core/src/java/org/apache/solr/search/function/distance/HaversineConstFunction.java (revision 1380665) +++ solr/core/src/java/org/apache/solr/search/function/distance/HaversineConstFunction.java (revision ) @@ -26,7 +26,7 @@ import org.apache.lucene.queries.function.valuesource.VectorValueSource; import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.search.IndexSearcher; -import com.spatial4j.core.context.ParseUtils; +import com.spatial4j.core.io.ParseUtils; import com.spatial4j.core.distance.DistanceUtils; import com.spatial4j.core.exception.InvalidShapeException; import org.apache.solr.common.params.SpatialParams; @@ -39,20 +39,18 @@ import java.util.List; import java.util.Map; +import static com.spatial4j.core.distance.DistanceUtils.DEGREES_TO_RADIANS; /** * Haversine function with one point constant */ 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() { @Override public ValueSource parse(FunctionQParser fp) throws ParseException { - // TODO: dispatch through SpatialQueriable in the future? + // TODO: dispatch through SpatialQueryable in the future? List sources = fp.parseValueSourceList(); // "m" is a multi-value source, "x" is a single-value source Index: solr/core/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- solr/core/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java (revision 1380665) +++ solr/core/src/test/org/apache/solr/search/function/distance/DistanceFunctionTest.java (revision ) @@ -17,7 +17,7 @@ */ import com.spatial4j.core.distance.DistanceUtils; -import com.spatial4j.core.util.GeohashUtils; +import com.spatial4j.core.io.GeohashUtils; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.common.SolrException; import org.junit.BeforeClass; Index: dev-tools/maven/pom.xml.template IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- dev-tools/maven/pom.xml.template (revision 1380665) +++ dev-tools/maven/pom.xml.template (revision ) @@ -370,7 +370,7 @@ com.spatial4j spatial4j - 0.2 + 0.3 xerces Index: lucene/spatial/build.xml IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/build.xml (revision 1380665) +++ lucene/spatial/build.xml (revision ) @@ -7,7 +7,7 @@ - + Index: lucene/spatial/src/java/org/apache/lucene/spatial/prefix/tree/SpatialPrefixTree.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/java/org/apache/lucene/spatial/prefix/tree/SpatialPrefixTree.java (revision 1380665) +++ lucene/spatial/src/java/org/apache/lucene/spatial/prefix/tree/SpatialPrefixTree.java (revision ) @@ -83,8 +83,6 @@ // and this is the longest distance that might be occurring within the shape. double diagonalDist = ctx.getDistCalc().distance( ctx.makePoint(bbox.getMinX(), bbox.getMinY()), bbox.getMaxX(), bbox.getMaxY()); - //convert to degrees //TODO not needed in Spatial4j 0.3 - diagonalDist = ctx.getDistCalc().distanceToDegrees(diagonalDist); return getLevelForDistance(diagonalDist * 0.5 * precision); } Index: solr/core/src/java/org/apache/solr/schema/LatLonType.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- solr/core/src/java/org/apache/solr/schema/LatLonType.java (revision 1380665) +++ solr/core/src/java/org/apache/solr/schema/LatLonType.java (revision ) @@ -17,8 +17,6 @@ */ import org.apache.lucene.document.FieldType; -import org.apache.lucene.index.GeneralField; -import org.apache.lucene.index.IndexableField; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.index.StorableField; @@ -26,12 +24,9 @@ import org.apache.lucene.queries.function.ValueSource; import org.apache.lucene.queries.function.valuesource.VectorValueSource; import org.apache.lucene.search.*; -import com.spatial4j.core.context.ParseUtils; +import com.spatial4j.core.io.ParseUtils; import com.spatial4j.core.context.SpatialContext; -import com.spatial4j.core.context.simple.SimpleSpatialContext; -import com.spatial4j.core.distance.DistanceCalculator; import com.spatial4j.core.distance.DistanceUtils; -import com.spatial4j.core.distance.GeodesicSphereDistCalc; import com.spatial4j.core.exception.InvalidShapeException; import com.spatial4j.core.shape.Rectangle; import org.apache.lucene.util.Bits; @@ -149,9 +144,8 @@ double latCenter = point[LAT]; double lonCenter = point[LON]; - DistanceCalculator distCalc = new GeodesicSphereDistCalc.Haversine(options.units.earthRadius()); - SpatialContext ctx = new SimpleSpatialContext(options.units,distCalc,null); - Rectangle bbox = DistanceUtils.calcBoxByDistFromPtDEG(latCenter, lonCenter, options.distance, ctx); + double distDeg = DistanceUtils.dist2Degrees(options.distance, options.radius); + Rectangle bbox = DistanceUtils.calcBoxByDistFromPtDEG(latCenter, lonCenter, distDeg, SpatialContext.GEO, null); double latMin = bbox.getMinY(); double latMax = bbox.getMaxY(); double lonMin, lonMax, lon2Min, lon2Max; @@ -403,8 +397,8 @@ this.lon2 = SpatialDistanceQuery.this.lon2; this.calcDist = SpatialDistanceQuery.this.calcDist; - this.latCenterRad = SpatialDistanceQuery.this.latCenter * HaversineConstFunction.DEGREES_TO_RADIANS; - this.lonCenterRad = SpatialDistanceQuery.this.lonCenter * HaversineConstFunction.DEGREES_TO_RADIANS; + this.latCenterRad = SpatialDistanceQuery.this.latCenter * DistanceUtils.DEGREES_TO_RADIANS; + this.lonCenterRad = SpatialDistanceQuery.this.lonCenter * DistanceUtils.DEGREES_TO_RADIANS; this.latCenterRad_cos = this.calcDist ? Math.cos(latCenterRad) : 0; this.dist = SpatialDistanceQuery.this.dist; this.planetRadius = SpatialDistanceQuery.this.planetRadius; @@ -433,8 +427,8 @@ } double dist(double lat, double lon) { - double latRad = lat * HaversineConstFunction.DEGREES_TO_RADIANS; - double lonRad = lon * HaversineConstFunction.DEGREES_TO_RADIANS; + double latRad = lat * DistanceUtils.DEGREES_TO_RADIANS; + double lonRad = lon * DistanceUtils.DEGREES_TO_RADIANS; // haversine, specialized to avoid a cos() call on latCenterRad double diffX = latCenterRad - latRad; @@ -599,7 +593,7 @@ /** Returns a hash code value for this object. */ @Override public int hashCode() { - // don't bother making the hash expensive - the center latitude + min longitude will be very uinque + // don't bother making the hash expensive - the center latitude + min longitude will be very unique long hash = Double.doubleToLongBits(latCenter); hash = hash * 31 + Double.doubleToLongBits(lonMin); hash = hash * 31 + (long)super.hashCode(); Index: solr/core/src/java/org/apache/solr/schema/GeoHashField.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- solr/core/src/java/org/apache/solr/schema/GeoHashField.java (revision 1380665) +++ solr/core/src/java/org/apache/solr/schema/GeoHashField.java (revision ) @@ -19,16 +19,13 @@ import org.apache.lucene.queries.function.ValueSource; import org.apache.lucene.queries.function.valuesource.LiteralValueSource; -import org.apache.lucene.index.GeneralField; -import org.apache.lucene.index.IndexableField; import org.apache.lucene.index.StorableField; import org.apache.lucene.search.Query; import org.apache.lucene.search.SortField; -import com.spatial4j.core.context.ParseUtils; +import com.spatial4j.core.io.ParseUtils; import com.spatial4j.core.context.SpatialContext; -import com.spatial4j.core.context.simple.SimpleSpatialContext; import com.spatial4j.core.exception.InvalidShapeException; -import com.spatial4j.core.util.GeohashUtils; +import com.spatial4j.core.io.GeohashUtils; import com.spatial4j.core.shape.Point; import org.apache.solr.common.SolrException; import org.apache.solr.response.TextResponseWriter; @@ -46,12 +43,12 @@ * href="http://en.wikipedia.org/wiki/Geohash">Geohash field. The field is * provided as a lat/lon pair and is internally represented as a string. * - * @see com.spatial4j.core.context.ParseUtils#parseLatitudeLongitude(double[], String) + * @see com.spatial4j.core.io.ParseUtils#parseLatitudeLongitude(double[], String) */ public class GeoHashField extends FieldType implements SpatialQueryable { - private final SpatialContext ctx = SimpleSpatialContext.GEO_KM; + private final SpatialContext ctx = SpatialContext.GEO; @Override public SortField getSortField(SchemaField field, boolean top) { Index: lucene/spatial/src/test/org/apache/lucene/spatial/query/SpatialArgsParserTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/test/org/apache/lucene/spatial/query/SpatialArgsParserTest.java (revision 1380665) +++ lucene/spatial/src/test/org/apache/lucene/spatial/query/SpatialArgsParserTest.java (revision ) @@ -18,7 +18,6 @@ */ import com.spatial4j.core.context.SpatialContext; -import com.spatial4j.core.context.simple.SimpleSpatialContext; import com.spatial4j.core.shape.Rectangle; import org.apache.lucene.util.LuceneTestCase; import org.junit.Test; @@ -26,7 +25,7 @@ public class SpatialArgsParserTest extends LuceneTestCase { - private SpatialContext ctx = SimpleSpatialContext.GEO_KM; + private SpatialContext ctx = SpatialContext.GEO; //The args parser is only dependent on the ctx for IO so I don't care to test // with other implementations. Index: lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialArgs.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialArgs.java (revision 1380665) +++ lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialArgs.java (revision ) @@ -19,7 +19,6 @@ import java.util.Locale; -import com.spatial4j.core.exception.InvalidSpatialArgument; import com.spatial4j.core.shape.Shape; /** @@ -45,9 +44,9 @@ } /** Check if the arguments make sense -- throw an exception if not */ - public void validate() throws InvalidSpatialArgument { + public void validate() throws IllegalArgumentException { if (operation.isTargetNeedsArea() && !shape.hasArea()) { - throw new InvalidSpatialArgument(operation + " only supports geometry with area"); + throw new IllegalArgumentException(operation + " only supports geometry with area"); } } Index: lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialArgsParser.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialArgsParser.java (revision 1380665) +++ lucene/spatial/src/java/org/apache/lucene/spatial/query/SpatialArgsParser.java (revision ) @@ -19,7 +19,7 @@ import com.spatial4j.core.context.SpatialContext; import com.spatial4j.core.exception.InvalidShapeException; -import com.spatial4j.core.exception.InvalidSpatialArgument; +import com.spatial4j.core.io.ShapeReadWriter; import com.spatial4j.core.shape.Shape; import java.util.HashMap; @@ -30,7 +30,7 @@ * Parses a string that usually looks like "OPERATION(SHAPE)" into a {@link SpatialArgs} * object. The set of operations supported are defined in {@link SpatialOperation}, such * as "Intersects" being a common one. The shape portion is defined by {@link - * SpatialContext#readShape(String)}. There are some optional name-value pair parameters + * ShapeReadWriter#readShape(String)}. There are some optional name-value pair parameters * that follow the closing parenthesis. Example: *
  *   Intersects(-10,20,-8,22) distPec=0.025
@@ -50,25 +50,25 @@
    * @param v   The string to parse. Mandatory.
    * @param ctx The spatial context. Mandatory.
    * @return Not null.
-   * @throws InvalidSpatialArgument If there is a problem parsing the string.
-   * @throws InvalidShapeException  Thrown from {@link SpatialContext#readShape(String)}
+   * @throws IllegalArgumentException If there is a problem parsing the string.
+   * @throws InvalidShapeException  Thrown from {@link ShapeReadWriter#readShape(String)}
    */
-  public SpatialArgs parse(String v, SpatialContext ctx) throws InvalidSpatialArgument, InvalidShapeException {
+  public SpatialArgs parse(String v, SpatialContext ctx) throws IllegalArgumentException, InvalidShapeException {
     int idx = v.indexOf('(');
     int edx = v.lastIndexOf(')');
 
     if (idx < 0 || idx > edx) {
-      throw new InvalidSpatialArgument("missing parens: " + v, null);
+      throw new IllegalArgumentException("missing parens: " + v, null);
     }
 
     SpatialOperation op = SpatialOperation.get(v.substring(0, idx).trim());
 
     String body = v.substring(idx + 1, edx).trim();
     if (body.length() < 1) {
-      throw new InvalidSpatialArgument("missing body : " + v, null);
+      throw new IllegalArgumentException("missing body : " + v, null);
     }
 
-    Shape shape = ctx.readShape(body);
+    Shape shape = new ShapeReadWriter(ctx).readShape(body);
     SpatialArgs args = new SpatialArgs(op, shape);
 
     if (v.length() > (edx + 1)) {
@@ -77,7 +77,7 @@
         Map aa = parseMap(body);
         args.setDistPrecision(readDouble(aa.remove("distPrec")));
         if (!aa.isEmpty()) {
-          throw new InvalidSpatialArgument("unused parameters: " + aa, null);
+          throw new IllegalArgumentException("unused parameters: " + aa, null);
         }
       }
     }
Index: lucene/spatial/src/test/org/apache/lucene/spatial/prefix/TestRecursivePrefixTreeStrategy.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/test/org/apache/lucene/spatial/prefix/TestRecursivePrefixTreeStrategy.java	(revision 1380665)
+++ lucene/spatial/src/test/org/apache/lucene/spatial/prefix/TestRecursivePrefixTreeStrategy.java	(revision )
@@ -17,18 +17,16 @@
  * limitations under the License.
  */
 
-import com.spatial4j.core.context.simple.SimpleSpatialContext;
+import com.spatial4j.core.context.SpatialContext;
 import com.spatial4j.core.distance.DistanceUtils;
 import com.spatial4j.core.shape.Point;
 import com.spatial4j.core.shape.Rectangle;
 import com.spatial4j.core.shape.Shape;
-import com.spatial4j.core.shape.simple.PointImpl;
-import com.spatial4j.core.util.GeohashUtils;
+import com.spatial4j.core.io.GeohashUtils;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.StoredField;
 import org.apache.lucene.document.StringField;
-import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.spatial.SpatialMatchConcern;
 import org.apache.lucene.spatial.StrategyTestCase;
 import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree;
@@ -43,8 +41,6 @@
 import java.util.List;
 import java.util.Set;
 
-import static java.lang.Math.toRadians;
-
 public class TestRecursivePrefixTreeStrategy extends StrategyTestCase {
 
   private int maxLength;
@@ -52,7 +48,7 @@
   //Tests should call this first.
   private void init(int maxLength) {
     this.maxLength = maxLength;
-    this.ctx = SimpleSpatialContext.GEO_KM;
+    this.ctx = SpatialContext.GEO;
     GeohashPrefixTree grid = new GeohashPrefixTree(ctx, maxLength);
     this.strategy = new RecursivePrefixTreeStrategy(grid, getClass().getSimpleName());
   }
@@ -74,7 +70,8 @@
     init(GeohashPrefixTree.getMaxLevelsPossible());
     GeohashPrefixTree grid = (GeohashPrefixTree) ((RecursivePrefixTreeStrategy) strategy).getGrid();
     //DWS: I know this to be true.  11 is needed for one meter
-    assertEquals(11, grid.getLevelForDistance(ctx.getDistCalc().distanceToDegrees(0.001)));
+    double degrees = DistanceUtils.dist2Degrees(0.001, DistanceUtils.EARTH_MEAN_RADIUS_KM);
+    assertEquals(11, grid.getLevelForDistance(degrees));
   }
 
   @Test
@@ -87,8 +84,11 @@
 
     Point qPt = ctx.makePoint(2.4632387000000335, 48.6003516);
 
+    final double KM2DEG = DistanceUtils.dist2Degrees(1, DistanceUtils.EARTH_MEAN_RADIUS_KM);
+    final double DEG2KM = 1 / KM2DEG;
+
     final double DIST = 35.75;//35.7499...
-    assertEquals(DIST, ctx.getDistCalc().distance(iPt, qPt), 0.001);
+    assertEquals(DIST, ctx.getDistCalc().distance(iPt, qPt) * DEG2KM, 0.001);
 
     //distPrec will affect the query shape precision. The indexed precision
     // was set to nearly zilch via init(GeohashPrefixTree.getMaxLevelsPossible());
@@ -96,16 +96,16 @@
     final double distMult = 1+distPrec;
 
     assertTrue(35.74*distMult >= DIST);
-    checkHits(q(qPt, 35.74, distPrec), 1, null);
+    checkHits(q(qPt, 35.74 * KM2DEG, distPrec), 1, null);
 
     assertTrue(30*distMult < DIST);
-    checkHits(q(qPt, 30, distPrec), 0, null);
+    checkHits(q(qPt, 30 * KM2DEG, distPrec), 0, null);
 
     assertTrue(33*distMult < DIST);
-    checkHits(q(qPt, 33, distPrec), 0, null);
+    checkHits(q(qPt, 33 * KM2DEG, distPrec), 0, null);
 
     assertTrue(34*distMult < DIST);
-    checkHits(q(qPt, 34, distPrec), 0, null);
+    checkHits(q(qPt, 34 * KM2DEG, distPrec), 0, null);
   }
 
   @Test
@@ -113,70 +113,72 @@
     init(12);
 
     //1. Iterate test with the cluster at some worldly point of interest
-    Point[] clusterCenters = new Point[]{new PointImpl(0,0), new PointImpl(0,90),new PointImpl(0,-90)};
+    Point[] clusterCenters = new Point[]{ctx.makePoint(0,0), ctx.makePoint(0,90), ctx.makePoint(0,-90)};
     for (Point clusterCenter : clusterCenters) {
       //2. Iterate on size of cluster (a really small one and a large one)
       String hashCenter = GeohashUtils.encodeLatLon(clusterCenter.getY(), clusterCenter.getX(), maxLength);
       //calculate the number of degrees in the smallest grid box size (use for both lat & lon)
       String smallBox = hashCenter.substring(0,hashCenter.length()-1);//chop off leaf precision
       Rectangle clusterDims = GeohashUtils.decodeBoundary(smallBox,ctx);
-      double smallDegrees = Math.max(clusterDims.getMaxX()-clusterDims.getMinX(),clusterDims.getMaxY()-clusterDims.getMinY());
-      assert smallDegrees < 1;
-      double largeDegrees = 20d;//good large size; don't use >=45 for this test code to work
-      double[] sideDegrees = {largeDegrees,smallDegrees};
-      for (double sideDegree : sideDegrees) {
-        //3. Index random points in this cluster box
+      double smallRadius = Math.max(clusterDims.getMaxX()-clusterDims.getMinX(),clusterDims.getMaxY()-clusterDims.getMinY());
+      assert smallRadius < 1;
+      double largeRadius = 20d;//good large size; don't use >=45 for this test code to work
+      double[] radiusDegs = {largeRadius,smallRadius};
+      for (double radiusDeg : radiusDegs) {
+        //3. Index random points in this cluster circle
         deleteAll();
         List points = new ArrayList();
         for(int i = 0; i < 20; i++) {
-          double x = random().nextDouble()*sideDegree - sideDegree/2 + clusterCenter.getX();
-          double y = random().nextDouble()*sideDegree - sideDegree/2 + clusterCenter.getY();
-          final Point pt = normPointXY(x, y);
+          //Note that this will not result in randomly distributed points in the
+          // circle, they will be concentrated towards the center a little. But
+          // it's good enough.
+          Point pt = ctx.getDistCalc().pointOnBearing(clusterCenter,
+              random().nextDouble() * radiusDeg, random().nextInt() * 360, ctx, null);
+          pt = alignGeohash(pt);
           points.add(pt);
           addDocument(newDoc("" + i, pt));
         }
         commit();
 
-        //3. Use 4 query centers. Each is radially out from each corner of cluster box by twice distance to box edge.
-        for(double qcXoff : new double[]{sideDegree,-sideDegree}) {//query-center X offset from cluster center
-          for(double qcYoff : new double[]{sideDegree,-sideDegree}) {//query-center Y offset from cluster center
-            Point queryCenter = normPointXY(qcXoff + clusterCenter.getX(),
-                qcYoff + clusterCenter.getY());
-            double[] distRange = calcDistRange(queryCenter,clusterCenter,sideDegree);
-            //4.1 query a small box getting nothing
-            checkHits(q(queryCenter, distRange[0]*0.99), 0, null);
+        //3. Use some query centers. Each is twice the cluster's radius away.
+        for(int ri = 0; ri < 4; ri++) {
+          Point queryCenter = ctx.getDistCalc().pointOnBearing(clusterCenter,
+              radiusDeg*2, random().nextInt() * 360, ctx, null);
+          queryCenter = alignGeohash(queryCenter);
+          //4.1 Query a small box getting nothing
+          checkHits(q(queryCenter, radiusDeg*0.99), 0, null);
-            //4.2 Query a large box enclosing the cluster, getting everything
+          //4.2 Query a large box enclosing the cluster, getting everything
-            checkHits(q(queryCenter, distRange[1]*1.01), points.size(), null);
+          checkHits(q(queryCenter, radiusDeg*3*1.01), points.size(), null);
-            //4.3 Query a medium box getting some (calculate the correct solution and verify)
+          //4.3 Query a medium box getting some (calculate the correct solution and verify)
-            double queryDist = distRange[0] + (distRange[1]-distRange[0])/2;//average
+          double queryDist = radiusDeg * 2;
 
-            //Find matching points.  Put into int[] of doc ids which is the same thing as the index into points list.
-            int[] ids = new int[points.size()];
-            int ids_sz = 0;
-            for (int i = 0; i < points.size(); i++) {
-              Point point = points.get(i);
-              if (ctx.getDistCalc().distance(queryCenter, point) <= queryDist)
-                ids[ids_sz++] = i;
-            }
-            ids = Arrays.copyOf(ids, ids_sz);
-            //assert ids_sz > 0 (can't because randomness keeps us from being able to)
+          //Find matching points.  Put into int[] of doc ids which is the same thing as the index into points list.
+          int[] ids = new int[points.size()];
+          int ids_sz = 0;
+          for (int i = 0; i < points.size(); i++) {
+            Point point = points.get(i);
+            if (ctx.getDistCalc().distance(queryCenter, point) <= queryDist)
+              ids[ids_sz++] = i;
+          }
+          ids = Arrays.copyOf(ids, ids_sz);
+          //assert ids_sz > 0 (can't because randomness keeps us from being able to)
 
-            checkHits(q(queryCenter, queryDist), ids.length, ids);
-          }
+          checkHits(q(queryCenter, queryDist), ids.length, ids);
+        }
-        }
 
-      }//for sideDegree
+      }//for radiusDeg
 
     }//for clusterCenter
 
   }//randomTest()
 
-  private SpatialArgs q(Point pt, double dist) {
-    return q(pt, dist, 0.0);
+  /** Query point-distance (in degrees) with zero error percent. */
+  private SpatialArgs q(Point pt, double distDEG) {
+    return q(pt, distDEG, 0.0);
   }
 
-  private SpatialArgs q(Point pt, double dist, double distPrec) {
-    Shape shape = ctx.makeCircle(pt,dist);
+  private SpatialArgs q(Point pt, double distDEG, double distPrec) {
+    Shape shape = ctx.makeCircle(pt, distDEG);
     SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects,shape);
     args.setDistPrecision(distPrec);
     return args;
@@ -207,30 +209,8 @@
     return doc;
   }
 
-  private double[] calcDistRange(Point startPoint, Point targetCenter, double targetSideDegrees) {
-    double min = Double.MAX_VALUE;
-    double max = Double.MIN_VALUE;
-    for(double xLen : new double[]{targetSideDegrees,-targetSideDegrees}) {
-      for(double yLen : new double[]{targetSideDegrees,-targetSideDegrees}) {
-        Point p2 = normPointXY(targetCenter.getX() + xLen / 2, targetCenter.getY() + yLen / 2);
-        double d = ctx.getDistCalc().distance(startPoint, p2);
-        min = Math.min(min,d);
-        max = Math.max(max,d);
-      }
-    }
-    return new double[]{min,max};
-  }
-
-  /** Normalize x & y (put in lon-lat ranges) & ensure geohash round-trip for given precision. */
-  private Point normPointXY(double x, double y) {
-    //put x,y as degrees into double[] as radians
-    double[] latLon = {y*DistanceUtils.DEG_180_AS_RADS, toRadians(x)};
-    DistanceUtils.normLatRAD(latLon);
-    DistanceUtils.normLatRAD(latLon);
-    double x2 = Math.toDegrees(latLon[1]);
-    double y2 = Math.toDegrees(latLon[0]);
-    //overwrite latLon, units is now degrees
-
-    return GeohashUtils.decode(GeohashUtils.encodeLatLon(y2, x2, maxLength),ctx);
+  /** NGeohash round-trip for given precision. */
+  private Point alignGeohash(Point p) {
+    return GeohashUtils.decode(GeohashUtils.encodeLatLon(p.getY(), p.getX(), maxLength), ctx);
   }
 }
Index: solr/core/src/java/org/apache/solr/search/function/distance/GeohashFunction.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- solr/core/src/java/org/apache/solr/search/function/distance/GeohashFunction.java	(revision 1380665)
+++ solr/core/src/java/org/apache/solr/search/function/distance/GeohashFunction.java	(revision )
@@ -19,7 +19,7 @@
 import org.apache.lucene.index.AtomicReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
-import com.spatial4j.core.util.GeohashUtils;
+import com.spatial4j.core.io.GeohashUtils;
 
 import java.util.Map;
 import java.io.IOException;
Index: lucene/spatial/src/test/org/apache/lucene/spatial/TestTestFramework.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/test/org/apache/lucene/spatial/TestTestFramework.java	(revision 1380665)
+++ lucene/spatial/src/test/org/apache/lucene/spatial/TestTestFramework.java	(revision )
@@ -18,7 +18,7 @@
  */
 
 import com.spatial4j.core.context.SpatialContext;
-import com.spatial4j.core.context.simple.SimpleSpatialContext;
+import com.spatial4j.core.context.SpatialContext;
 import com.spatial4j.core.shape.Rectangle;
 import org.apache.lucene.spatial.query.SpatialArgsParser;
 import org.apache.lucene.spatial.query.SpatialOperation;
@@ -43,7 +43,7 @@
     String name = StrategyTestCase.QTEST_Cities_IsWithin_BBox;
 
     InputStream in = getClass().getClassLoader().getResourceAsStream(name);
-    SpatialContext ctx = SimpleSpatialContext.GEO_KM;
+    SpatialContext ctx = SpatialContext.GEO;
     Iterator iter = SpatialTestQuery.getTestQueries(
         new SpatialArgsParser(), ctx, name, in );
     List tests = new ArrayList();
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 1380665)
+++ lucene/spatial/src/java/org/apache/lucene/spatial/prefix/PrefixTreeStrategy.java	(revision )
@@ -25,7 +25,6 @@
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.FieldType;
 import org.apache.lucene.index.FieldInfo;
-import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.spatial.SpatialStrategy;
 import org.apache.lucene.spatial.prefix.tree.Node;
Index: lucene/spatial/src/java/org/apache/lucene/spatial/prefix/tree/SpatialPrefixTreeFactory.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/java/org/apache/lucene/spatial/prefix/tree/SpatialPrefixTreeFactory.java	(revision 1380665)
+++ lucene/spatial/src/java/org/apache/lucene/spatial/prefix/tree/SpatialPrefixTreeFactory.java	(revision )
@@ -18,7 +18,6 @@
 package org.apache.lucene.spatial.prefix.tree;
 
 import com.spatial4j.core.context.SpatialContext;
-import com.spatial4j.core.distance.DistanceUnits;
 import com.spatial4j.core.distance.DistanceUtils;
 
 import java.util.Map;
@@ -78,11 +77,14 @@
       if (!ctx.isGeo()) {
         return;//let default to max
       }
-      degrees = DistanceUtils.dist2Degrees(DEFAULT_GEO_MAX_DETAIL_KM, DistanceUnits.KILOMETERS.earthRadius());
+      degrees = DistanceUtils.dist2Degrees(DEFAULT_GEO_MAX_DETAIL_KM, DistanceUtils.EARTH_MEAN_RADIUS_KM);
     } else {
-      degrees = DistanceUtils.dist2Degrees(Double.parseDouble(maxDetailDistStr), ctx.getUnits().earthRadius());
+      degrees = Double.parseDouble(maxDetailDistStr);
+      if (ctx.isGeo()) {
+        degrees = DistanceUtils.dist2Degrees(Double.parseDouble(maxDetailDistStr), DistanceUtils.EARTH_MEAN_RADIUS_KM);
-    }
+      }
-    maxLevels = getLevelForDistance(degrees) + 1;//returns 1 greater
+    }
+    maxLevels = getLevelForDistance(degrees);
   }
 
   /** Calls {@link SpatialPrefixTree#getLevelForDistance(double)}. */
Index: lucene/spatial/src/java/org/apache/lucene/spatial/prefix/tree/Node.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lucene/spatial/src/java/org/apache/lucene/spatial/prefix/tree/Node.java	(revision 1380665)
+++ lucene/spatial/src/java/org/apache/lucene/spatial/prefix/tree/Node.java	(revision )
@@ -152,7 +152,7 @@
     }
     List copy = new ArrayList(cells.size());//copy since cells contractually isn't modifiable
     for (Node cell : cells) {
-      SpatialRelation rel = cell.getShape().relate(shapeFilter, spatialPrefixTree.ctx);
+      SpatialRelation rel = cell.getShape().relate(shapeFilter);
       if (rel == SpatialRelation.DISJOINT)
         continue;
       cell.shapeRel = rel;
Index: solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- solr/core/src/java/org/apache/solr/search/ValueSourceParser.java	(revision 1380665)
+++ solr/core/src/java/org/apache/solr/search/ValueSourceParser.java	(revision )
@@ -16,6 +16,7 @@
  */
 package org.apache.solr.search;
 
+import com.spatial4j.core.distance.DistanceUtils;
 import org.apache.lucene.index.AtomicReaderContext;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.queries.function.BoostedQuery;
@@ -398,13 +399,13 @@
     addParser(new DoubleParser("rad") {
       @Override
       public double func(int doc, FunctionValues vals) {
-        return vals.doubleVal(doc) * HaversineConstFunction.DEGREES_TO_RADIANS;
+        return vals.doubleVal(doc) * DistanceUtils.DEGREES_TO_RADIANS;
       }
     });
     addParser(new DoubleParser("deg") {
       @Override
       public double func(int doc, FunctionValues vals) {
-        return vals.doubleVal(doc) * HaversineConstFunction.RADIANS_TO_DEGREES;
+        return vals.doubleVal(doc) * DistanceUtils.RADIANS_TO_DEGREES;
       }
     });
     addParser(new DoubleParser("sqrt") {
Index: solr/core/src/java/org/apache/solr/search/function/distance/GeohashHaversineFunction.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- solr/core/src/java/org/apache/solr/search/function/distance/GeohashHaversineFunction.java	(revision 1380665)
+++ solr/core/src/java/org/apache/solr/search/function/distance/GeohashHaversineFunction.java	(revision )
@@ -17,21 +17,19 @@
  */
 
 
+import com.spatial4j.core.context.SpatialContext;
+import com.spatial4j.core.distance.DistanceUtils;
+import com.spatial4j.core.distance.GeodesicSphereDistCalc;
+import com.spatial4j.core.io.GeohashUtils;
+import com.spatial4j.core.shape.Point;
+import org.apache.lucene.index.AtomicReaderContext;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
-import org.apache.lucene.index.AtomicReaderContext;
 import org.apache.lucene.search.IndexSearcher;
-import com.spatial4j.core.context.SpatialContext;
-import com.spatial4j.core.context.simple.SimpleSpatialContext;
-import com.spatial4j.core.distance.DistanceCalculator;
-import com.spatial4j.core.distance.DistanceUnits;
-import com.spatial4j.core.distance.GeodesicSphereDistCalc;
-import com.spatial4j.core.util.GeohashUtils;
-import com.spatial4j.core.shape.Point;
 
-import java.util.Map;
 import java.io.IOException;
+import java.util.Map;
 
 
 /**
@@ -46,16 +44,16 @@
  **/
 public class GeohashHaversineFunction extends ValueSource {
 
-  private ValueSource geoHash1, geoHash2;
-  private double radius;
+  private final ValueSource geoHash1, geoHash2;
   private final SpatialContext ctx;
+  private final double degreesToDist;
 
   public GeohashHaversineFunction(ValueSource geoHash1, ValueSource geoHash2, double radius) {
     this.geoHash1 = geoHash1;
     this.geoHash2 = geoHash2;
-    this.radius = radius;
-    DistanceCalculator distCalc = new GeodesicSphereDistCalc.Haversine(radius);
-    this.ctx = new SimpleSpatialContext(DistanceUnits.KILOMETERS,distCalc,null);
+    this.degreesToDist = DistanceUtils.degrees2Dist(1, radius);
+    this.ctx = SpatialContext.GEO;
+    assert this.ctx.getDistCalc() instanceof GeodesicSphereDistCalc.Haversine;
   }
 
   protected String name() {
@@ -92,7 +90,7 @@
       //and avoid decoding every time
       Point p1 = GeohashUtils.decode(h1,ctx);
       Point p2 = GeohashUtils.decode(h2,ctx);
-      result = ctx.getDistCalc().distance(p1, p2);
+      result = ctx.getDistCalc().distance(p1, p2) * degreesToDist;
     } else if (h1 == null || h2 == null){
       result = Double.MAX_VALUE;
     }
@@ -112,7 +110,7 @@
     return this.name().equals(other.name())
             && geoHash1.equals(other.geoHash1) &&
             geoHash2.equals(other.geoHash2) &&
-            radius == other.radius;
+            degreesToDist == other.degreesToDist;
   }
 
   @Override
@@ -121,7 +119,7 @@
     result = geoHash1.hashCode();
     result = 31 * result + geoHash2.hashCode();
     result = 31 * result + name().hashCode();
-    long temp =Double.doubleToRawLongBits(radius);
+    long temp =Double.doubleToRawLongBits(degreesToDist);
     result = 31 * result + (int) (temp ^ (temp >>> 32));
     return result;
   }