From 951563aa427ff685d67b3edf55999d72fa945045 Mon Sep 17 00:00:00 2001 From: nknize Date: Fri, 1 Apr 2016 13:12:34 -0500 Subject: [PATCH] LUCENE-7163: refactor GeoRect, Polygon, and GeoUtils tests to geo package in core. --- .../java/org/apache/lucene/geo}/Polygon.java | 62 +++++----- .../org/apache/lucene/geo/Rectangle.java} | 16 ++- .../org/apache/lucene/geo}/TestGeoUtils.java | 115 ++++-------------- .../apache/lucene/document/LatLonPoint.java | 2 +- .../LatLonPointDistanceComparator.java | 5 +- .../document/LatLonPointDistanceQuery.java | 8 +- .../document/LatLonPointInPolygonQuery.java | 6 +- .../document/TestLatLonPointDistanceSort.java | 2 +- .../lucene/search/TestLatLonPointQueries.java | 2 +- .../search/GeoPointDistanceQuery.java | 12 +- .../search/GeoPointDistanceQueryImpl.java | 8 +- .../search/GeoPointInPolygonQuery.java | 8 +- .../search/GeoPointInPolygonQueryImpl.java | 2 +- .../geopoint/search/TestGeoPointQuery.java | 2 +- .../search/TestLegacyGeoPointQuery.java | 2 +- .../spatial/util/BaseGeoPointTestCase.java | 17 +-- .../spatial/util/TestGeoEncodingUtils.java | 101 +++++++++++++++ .../lucene/spatial/util/TestPolygon.java | 19 ++- .../org/apache/lucene/geo}/GeoTestUtil.java | 71 ++++++----- .../org/apache/lucene/geo/package-info.java | 21 ++++ 20 files changed, 275 insertions(+), 206 deletions(-) rename lucene/{spatial/src/java/org/apache/lucene/spatial/util => core/src/java/org/apache/lucene/geo}/Polygon.java (92%) rename lucene/{spatial/src/java/org/apache/lucene/spatial/util/GeoRect.java => core/src/java/org/apache/lucene/geo/Rectangle.java} (93%) rename lucene/{spatial/src/test/org/apache/lucene/spatial/util => core/src/test/org/apache/lucene/geo}/TestGeoUtils.java (76%) create mode 100644 lucene/spatial/src/test/org/apache/lucene/spatial/util/TestGeoEncodingUtils.java rename lucene/{spatial/src/test/org/apache/lucene/spatial/util => test-framework/src/java/org/apache/lucene/geo}/GeoTestUtil.java (94%) create mode 100644 lucene/test-framework/src/java/org/apache/lucene/geo/package-info.java diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/util/Polygon.java b/lucene/core/src/java/org/apache/lucene/geo/Polygon.java similarity index 92% rename from lucene/spatial/src/java/org/apache/lucene/spatial/util/Polygon.java rename to lucene/core/src/java/org/apache/lucene/geo/Polygon.java index c0e23231de1..3f32920e148 100644 --- a/lucene/spatial/src/java/org/apache/lucene/spatial/util/Polygon.java +++ b/lucene/core/src/java/org/apache/lucene/geo/Polygon.java @@ -14,21 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.lucene.spatial.util; +package org.apache.lucene.geo; import java.util.Arrays; -import org.apache.lucene.geo.GeoUtils; - -/** +/** * Represents a closed polygon on the earth's surface. - * @lucene.experimental + * @lucene.experimental */ public final class Polygon { private final double[] polyLats; private final double[] polyLons; private final Polygon[] holes; - + /** minimum latitude of this polygon's bounding box area */ public final double minLat; /** maximum latitude of this polygon's bounding box area */ @@ -37,10 +35,13 @@ public final class Polygon { public final double minLon; /** maximum longitude of this polygon's bounding box area */ public final double maxLon; - + + // TODO: refactor to GeoUtils once LUCENE-7165 is complete + private static final double ENCODING_TOLERANCE = 1e-6; + // TODO: we could also compute the maximal inner bounding box, to make relations faster to compute? - - /** + + /** * Creates a new Polygon from the supplied latitude/longitude array, and optionally any holes. */ public Polygon(double[] polyLats, double[] polyLons, Polygon... holes) { @@ -99,14 +100,14 @@ public final class Polygon { this.minLon = minLon; this.maxLon = maxLon; } - + /** Returns true if the point is contained within this polygon */ public boolean contains(double latitude, double longitude) { // check bounding box if (latitude < minLat || latitude > maxLat || longitude < minLon || longitude > maxLon) { return false; } - /* + /* * simple even-odd point in polygon computation * 1. Determine if point is contained in the longitudinal range * 2. Determine whether point crosses the edge by computing the latitudinal delta @@ -139,7 +140,7 @@ public final class Polygon { return false; } } - + /** * Computes whether a rectangle is within a polygon (shared boundaries not allowed) */ @@ -149,9 +150,9 @@ public final class Polygon { boolean contains = crosses(minLat, maxLat, minLon, maxLon) == false && contains(minLat, minLon) && contains(minLat, maxLon) && - contains(maxLat, maxLon) && + contains(maxLat, maxLon) && contains(maxLat, minLon); - + if (contains) { // if we intersect with any hole, game over for (Polygon hole : holes) { @@ -164,7 +165,7 @@ public final class Polygon { return false; } } - + /** * Convenience method for accurately computing whether a rectangle crosses a poly. */ @@ -207,14 +208,15 @@ public final class Polygon { c2 = a2*polyLons[p+1] + b2*polyLats[p+1]; s = (1/d)*(b2*c1 - b1*c2); t = (1/d)*(a1*c2 - a2*c1); - x00 = Math.min(bbox[b][0], bbox[b+1][0]) - GeoEncodingUtils.TOLERANCE; - x01 = Math.max(bbox[b][0], bbox[b+1][0]) + GeoEncodingUtils.TOLERANCE; - y00 = Math.min(bbox[b][1], bbox[b+1][1]) - GeoEncodingUtils.TOLERANCE; - y01 = Math.max(bbox[b][1], bbox[b+1][1]) + GeoEncodingUtils.TOLERANCE; - x10 = Math.min(polyLons[p], polyLons[p+1]) - GeoEncodingUtils.TOLERANCE; - x11 = Math.max(polyLons[p], polyLons[p+1]) + GeoEncodingUtils.TOLERANCE; - y10 = Math.min(polyLats[p], polyLats[p+1]) - GeoEncodingUtils.TOLERANCE; - y11 = Math.max(polyLats[p], polyLats[p+1]) + GeoEncodingUtils.TOLERANCE; + // todo TOLERANCE SHOULD MATCH EVERYWHERE this is currently blocked by LUCENE-7165 + x00 = Math.min(bbox[b][0], bbox[b+1][0]) - ENCODING_TOLERANCE; + x01 = Math.max(bbox[b][0], bbox[b+1][0]) + ENCODING_TOLERANCE; + y00 = Math.min(bbox[b][1], bbox[b+1][1]) - ENCODING_TOLERANCE; + y01 = Math.max(bbox[b][1], bbox[b+1][1]) + ENCODING_TOLERANCE; + x10 = Math.min(polyLons[p], polyLons[p+1]) - ENCODING_TOLERANCE; + x11 = Math.max(polyLons[p], polyLons[p+1]) + ENCODING_TOLERANCE; + y10 = Math.min(polyLats[p], polyLats[p+1]) - ENCODING_TOLERANCE; + y11 = Math.max(polyLats[p], polyLats[p+1]) + ENCODING_TOLERANCE; // check whether the intersection point is touching one of the line segments boolean touching = ((x00 == s && y00 == t) || (x01 == s && y01 == t)) || ((x10 == s && y10 == t) || (x11 == s && y11 == t)); @@ -227,22 +229,22 @@ public final class Polygon { } // for each bbox edge return false; } - + /** Returns a copy of the internal latitude array */ public double[] getPolyLats() { return polyLats.clone(); } - + /** Returns a copy of the internal longitude array */ public double[] getPolyLons() { return polyLons.clone(); } - + /** Returns a copy of the internal holes array */ public Polygon[] getHoles() { return holes.clone(); } - + /** Helper for multipolygon logic: returns true if any of the supplied polygons contain the point */ public static boolean contains(Polygon[] polygons, double latitude, double longitude) { for (Polygon polygon : polygons) { @@ -252,7 +254,7 @@ public final class Polygon { } return false; } - + /** Helper for multipolygon logic: returns true if any of the supplied polygons contain the rectangle */ public static boolean contains(Polygon[] polygons, double minLat, double maxLat, double minLon, double maxLon) { for (Polygon polygon : polygons) { @@ -262,7 +264,7 @@ public final class Polygon { } return false; } - + /** Helper for multipolygon logic: returns true if any of the supplied polygons crosses the rectangle */ public static boolean crosses(Polygon[] polygons, double minLat, double maxLat, double minLon, double maxLon) { for (Polygon polygon : polygons) { @@ -272,7 +274,7 @@ public final class Polygon { } return false; } - + @Override public int hashCode() { final int prime = 31; diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRect.java b/lucene/core/src/java/org/apache/lucene/geo/Rectangle.java similarity index 93% rename from lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRect.java rename to lucene/core/src/java/org/apache/lucene/geo/Rectangle.java index fdde3bf12c5..527395ef3dd 100644 --- a/lucene/spatial/src/java/org/apache/lucene/spatial/util/GeoRect.java +++ b/lucene/core/src/java/org/apache/lucene/geo/Rectangle.java @@ -14,9 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.lucene.spatial.util; - -import org.apache.lucene.geo.GeoUtils; +package org.apache.lucene.geo; import static java.lang.Math.PI; import static java.lang.Math.max; @@ -38,7 +36,7 @@ import static org.apache.lucene.util.SloppyMath.asin; import static org.apache.lucene.util.SloppyMath.cos; /** Represents a lat/lon rectangle. */ -public class GeoRect { +public class Rectangle { /** maximum longitude value (in degrees) */ public final double minLat; /** minimum longitude value (in degrees) */ @@ -51,7 +49,7 @@ public class GeoRect { /** * Constructs a bounding box by first validating the provided latitude and longitude coordinates */ - public GeoRect(double minLat, double maxLat, double minLon, double maxLon) { + public Rectangle(double minLat, double maxLat, double minLon, double maxLon) { GeoUtils.checkLatitude(minLat); GeoUtils.checkLatitude(maxLat); GeoUtils.checkLongitude(minLon); @@ -90,7 +88,7 @@ public class GeoRect { } /** Compute Bounding Box for a circle using WGS-84 parameters */ - public static GeoRect fromPointDistance(final double centerLat, final double centerLon, final double radiusMeters) { + public static Rectangle fromPointDistance(final double centerLat, final double centerLon, final double radiusMeters) { checkLatitude(centerLat); checkLongitude(centerLon); final double radLat = toRadians(centerLat); @@ -120,7 +118,7 @@ public class GeoRect { maxLon = MAX_LON_RADIANS; } - return new GeoRect(toDegrees(minLat), toDegrees(maxLat), toDegrees(minLon), toDegrees(maxLon)); + return new Rectangle(toDegrees(minLat), toDegrees(maxLat), toDegrees(minLon), toDegrees(maxLon)); } /** maximum error from {@link #axisLat(double, double)}. logic must be prepared to handle this */ @@ -172,7 +170,7 @@ public class GeoRect { } /** Returns the bounding box over an array of polygons */ - public static GeoRect fromPolygon(Polygon[] polygons) { + public static Rectangle fromPolygon(Polygon[] polygons) { // compute bounding box double minLat = Double.POSITIVE_INFINITY; double maxLat = Double.NEGATIVE_INFINITY; @@ -186,6 +184,6 @@ public class GeoRect { maxLon = Math.max(polygons[i].maxLon, maxLon); } - return new GeoRect(minLat, maxLat, minLon, maxLon); + return new Rectangle(minLat, maxLat, minLon, maxLon); } } diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/util/TestGeoUtils.java b/lucene/core/src/test/org/apache/lucene/geo/TestGeoUtils.java similarity index 76% rename from lucene/spatial/src/test/org/apache/lucene/spatial/util/TestGeoUtils.java rename to lucene/core/src/test/org/apache/lucene/geo/TestGeoUtils.java index 28b885ae0b7..8727b42afa6 100644 --- a/lucene/spatial/src/test/org/apache/lucene/spatial/util/TestGeoUtils.java +++ b/lucene/core/src/test/org/apache/lucene/geo/TestGeoUtils.java @@ -14,12 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.lucene.spatial.util; +package org.apache.lucene.geo; import java.util.Locale; -import org.apache.lucene.geo.GeoUtils; -import org.apache.lucene.util.BytesRefBuilder; import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util.SloppyMath; import org.junit.BeforeClass; @@ -61,65 +59,6 @@ public class TestGeoUtils extends LuceneTestCase { return result; } - /** - * Tests stability of {@link GeoEncodingUtils#geoCodedToPrefixCoded} - */ - public void testGeoPrefixCoding() throws Exception { - int numIters = atLeast(1000); - long hash; - long decodedHash; - BytesRefBuilder brb = new BytesRefBuilder(); - while (numIters-- >= 0) { - hash = GeoEncodingUtils.mortonHash(randomLat(false), randomLon(false)); - for (int i=32; i<64; ++i) { - GeoEncodingUtils.geoCodedToPrefixCoded(hash, i, brb); - decodedHash = GeoEncodingUtils.prefixCodedToGeoCoded(brb.get()); - assertEquals((hash >>> i) << i, decodedHash); - } - } - } - - public void testMortonEncoding() throws Exception { - long hash = GeoEncodingUtils.mortonHash(90, 180); - assertEquals(180.0, GeoEncodingUtils.mortonUnhashLon(hash), 0); - assertEquals(90.0, GeoEncodingUtils.mortonUnhashLat(hash), 0); - } - - public void testEncodeDecode() throws Exception { - int iters = atLeast(10000); - boolean small = random().nextBoolean(); - for(int iter=0;iter radius); } catch (AssertionError e) { GeoTestUtil.toWebGLEarth(latMin, latMax, lonMin, lonMax, centerLat, centerLon, radius); @@ -381,9 +320,9 @@ public class TestGeoUtils extends LuceneTestCase { static double randomInRange(double min, double max) { return min + (max - min) * random().nextDouble(); } - + static boolean isDisjoint(double centerLat, double centerLon, double radius, double axisLat, double latMin, double latMax, double lonMin, double lonMax) { - if ((centerLon < lonMin || centerLon > lonMax) && (axisLat+GeoRect.AXISLAT_ERROR < latMin || axisLat-GeoRect.AXISLAT_ERROR > latMax)) { + if ((centerLon < lonMin || centerLon > lonMax) && (axisLat+ Rectangle.AXISLAT_ERROR < latMin || axisLat- Rectangle.AXISLAT_ERROR > latMax)) { // circle not fully inside / crossing axis if (SloppyMath.haversinMeters(centerLat, centerLon, latMin, lonMin) > radius && SloppyMath.haversinMeters(centerLat, centerLon, latMin, lonMax) > radius && @@ -393,7 +332,7 @@ public class TestGeoUtils extends LuceneTestCase { return true; } } - + return false; } } diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java index 507f543082e..26bb04ad5b6 100644 --- a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java +++ b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPoint.java @@ -29,7 +29,7 @@ import org.apache.lucene.search.FieldDoc; import org.apache.lucene.search.PointRangeQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.SortField; -import org.apache.lucene.spatial.util.Polygon; +import org.apache.lucene.geo.Polygon; /** * An indexed location field. diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointDistanceComparator.java b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointDistanceComparator.java index 0ed85adf09e..58db5e57e67 100644 --- a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointDistanceComparator.java +++ b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointDistanceComparator.java @@ -26,8 +26,7 @@ import org.apache.lucene.index.SortedNumericDocValues; import org.apache.lucene.search.FieldComparator; import org.apache.lucene.search.LeafFieldComparator; import org.apache.lucene.search.Scorer; -import org.apache.lucene.spatial.util.GeoRect; -import org.apache.lucene.geo.GeoUtils; +import org.apache.lucene.geo.Rectangle; import org.apache.lucene.util.SloppyMath; /** @@ -83,7 +82,7 @@ class LatLonPointDistanceComparator extends FieldComparator implements L // sampling if we get called way too much: don't make gobs of bounding // boxes if comparator hits a worst case order (e.g. backwards distance order) if (setBottomCounter < 1024 || (setBottomCounter & 0x3F) == 0x3F) { - GeoRect box = GeoRect.fromPointDistance(latitude, longitude, haversin2(bottom)); + Rectangle box = Rectangle.fromPointDistance(latitude, longitude, haversin2(bottom)); // pre-encode our box to our integer encoding, so we don't have to decode // to double values for uncompetitive hits. This has some cost! minLat = LatLonPoint.encodeLatitude(box.minLat); diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointDistanceQuery.java b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointDistanceQuery.java index 29347189f8b..1b667dd2500 100644 --- a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointDistanceQuery.java +++ b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointDistanceQuery.java @@ -18,6 +18,7 @@ package org.apache.lucene.document; import java.io.IOException; +import org.apache.lucene.geo.Rectangle; import org.apache.lucene.index.DocValues; import org.apache.lucene.index.FieldInfo; import org.apache.lucene.index.LeafReader; @@ -35,7 +36,6 @@ import org.apache.lucene.search.Query; import org.apache.lucene.search.Scorer; import org.apache.lucene.search.TwoPhaseIterator; import org.apache.lucene.search.Weight; -import org.apache.lucene.spatial.util.GeoRect; import org.apache.lucene.geo.GeoUtils; import org.apache.lucene.util.BitSet; import org.apache.lucene.util.DocIdSetBuilder; @@ -71,7 +71,7 @@ final class LatLonPointDistanceQuery extends Query { @Override public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException { - GeoRect box = GeoRect.fromPointDistance(latitude, longitude, radiusMeters); + Rectangle box = Rectangle.fromPointDistance(latitude, longitude, radiusMeters); // create bounding box(es) for the distance range // these are pre-encoded with LatLonPoint's encoding final byte minLat[] = new byte[Integer.BYTES]; @@ -108,7 +108,7 @@ final class LatLonPointDistanceQuery extends Query { maxPartialDistance = Double.POSITIVE_INFINITY; } - final double axisLat = GeoRect.axisLat(latitude, radiusMeters); + final double axisLat = Rectangle.axisLat(latitude, radiusMeters); return new ConstantScoreWeight(this) { @@ -196,7 +196,7 @@ final class LatLonPointDistanceQuery extends Query { double latMax = LatLonPoint.decodeLatitude(maxPackedValue, 0); double lonMax = LatLonPoint.decodeLongitude(maxPackedValue, Integer.BYTES); - if ((longitude < lonMin || longitude > lonMax) && (axisLat+GeoRect.AXISLAT_ERROR < latMin || axisLat-GeoRect.AXISLAT_ERROR > latMax)) { + if ((longitude < lonMin || longitude > lonMax) && (axisLat+ Rectangle.AXISLAT_ERROR < latMin || axisLat- Rectangle.AXISLAT_ERROR > latMax)) { // circle not fully inside / crossing axis if (SloppyMath.haversinMeters(latitude, longitude, latMin, lonMin) > radiusMeters && SloppyMath.haversinMeters(latitude, longitude, latMin, lonMax) > radiusMeters && diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointInPolygonQuery.java b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointInPolygonQuery.java index 56e906bc59d..54f5192074a 100644 --- a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointInPolygonQuery.java +++ b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonPointInPolygonQuery.java @@ -19,6 +19,7 @@ package org.apache.lucene.document; import java.io.IOException; import java.util.Arrays; +import org.apache.lucene.geo.Rectangle; import org.apache.lucene.index.PointValues.IntersectVisitor; import org.apache.lucene.index.PointValues.Relation; import org.apache.lucene.search.ConstantScoreScorer; @@ -42,8 +43,7 @@ import org.apache.lucene.util.FixedBitSet; import org.apache.lucene.util.NumericUtils; import org.apache.lucene.util.SparseFixedBitSet; import org.apache.lucene.util.StringHelper; -import org.apache.lucene.spatial.util.GeoRect; -import org.apache.lucene.spatial.util.Polygon; +import org.apache.lucene.geo.Polygon; /** Finds all previously indexed points that fall within the specified polygons. * @@ -84,7 +84,7 @@ final class LatLonPointInPolygonQuery extends Query { // bounding box over all polygons, this can speed up tree intersection/cheaply improve approximation for complex multi-polygons // these are pre-encoded with LatLonPoint's encoding - final GeoRect box = GeoRect.fromPolygon(polygons); + final Rectangle box = Rectangle.fromPolygon(polygons); final byte minLat[] = new byte[Integer.BYTES]; final byte maxLat[] = new byte[Integer.BYTES]; final byte minLon[] = new byte[Integer.BYTES]; diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPointDistanceSort.java b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPointDistanceSort.java index ac402b6b6f2..5ce819c98e9 100644 --- a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPointDistanceSort.java +++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPointDistanceSort.java @@ -19,6 +19,7 @@ package org.apache.lucene.document; import java.io.IOException; import java.util.Arrays; +import org.apache.lucene.geo.GeoTestUtil; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.RandomIndexWriter; @@ -29,7 +30,6 @@ import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; import org.apache.lucene.search.TopDocs; -import org.apache.lucene.spatial.util.GeoTestUtil; import org.apache.lucene.store.Directory; import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util.SloppyMath; diff --git a/lucene/sandbox/src/test/org/apache/lucene/search/TestLatLonPointQueries.java b/lucene/sandbox/src/test/org/apache/lucene/search/TestLatLonPointQueries.java index 3bde38971c3..08b9ebf6d7c 100644 --- a/lucene/sandbox/src/test/org/apache/lucene/search/TestLatLonPointQueries.java +++ b/lucene/sandbox/src/test/org/apache/lucene/search/TestLatLonPointQueries.java @@ -19,7 +19,7 @@ package org.apache.lucene.search; import org.apache.lucene.document.Document; import org.apache.lucene.document.LatLonPoint; import org.apache.lucene.spatial.util.BaseGeoPointTestCase; -import org.apache.lucene.spatial.util.Polygon; +import org.apache.lucene.geo.Polygon; public class TestLatLonPointQueries extends BaseGeoPointTestCase { diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointDistanceQuery.java b/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointDistanceQuery.java index c7ac6eb91fc..9e90a11af8c 100644 --- a/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointDistanceQuery.java +++ b/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointDistanceQuery.java @@ -21,7 +21,7 @@ import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.Query; import org.apache.lucene.spatial.geopoint.document.GeoPointField.TermEncoding; -import org.apache.lucene.spatial.util.GeoRect; +import org.apache.lucene.geo.Rectangle; import org.apache.lucene.geo.GeoUtils; /** Implements a simple point distance query on a GeoPoint field. This is based on @@ -80,10 +80,10 @@ public class GeoPointDistanceQuery extends GeoPointInBBoxQuery { * {@link org.apache.lucene.spatial.geopoint.document.GeoPointField.TermEncoding} parameter **/ public GeoPointDistanceQuery(final String field, final TermEncoding termEncoding, final double centerLat, final double centerLon, final double radiusMeters) { - this(field, termEncoding, GeoRect.fromPointDistance(centerLat, centerLon, checkRadius(radiusMeters)), centerLat, centerLon, radiusMeters); + this(field, termEncoding, Rectangle.fromPointDistance(centerLat, centerLon, checkRadius(radiusMeters)), centerLat, centerLon, radiusMeters); } - private GeoPointDistanceQuery(final String field, final TermEncoding termEncoding, final GeoRect bbox, + private GeoPointDistanceQuery(final String field, final TermEncoding termEncoding, final Rectangle bbox, final double centerLat, final double centerLon, final double radiusMeters) { super(field, termEncoding, bbox.minLat, bbox.maxLat, bbox.minLon, bbox.maxLon); @@ -105,7 +105,7 @@ public class GeoPointDistanceQuery extends GeoPointInBBoxQuery { unwrappedLon += -360.0D; } GeoPointDistanceQueryImpl left = new GeoPointDistanceQueryImpl(field, termEncoding, this, unwrappedLon, - new GeoRect(minLat, maxLat, GeoUtils.MIN_LON_INCL, maxLon)); + new Rectangle(minLat, maxLat, GeoUtils.MIN_LON_INCL, maxLon)); bqb.add(new BooleanClause(left, BooleanClause.Occur.SHOULD)); if (unwrappedLon < maxLon) { @@ -113,13 +113,13 @@ public class GeoPointDistanceQuery extends GeoPointInBBoxQuery { unwrappedLon += 360.0D; } GeoPointDistanceQueryImpl right = new GeoPointDistanceQueryImpl(field, termEncoding, this, unwrappedLon, - new GeoRect(minLat, maxLat, minLon, GeoUtils.MAX_LON_INCL)); + new Rectangle(minLat, maxLat, minLon, GeoUtils.MAX_LON_INCL)); bqb.add(new BooleanClause(right, BooleanClause.Occur.SHOULD)); return bqb.build(); } return new GeoPointDistanceQueryImpl(field, termEncoding, this, centerLon, - new GeoRect(this.minLat, this.maxLat, this.minLon, this.maxLon)); + new Rectangle(this.minLat, this.maxLat, this.minLon, this.maxLon)); } @Override diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointDistanceQueryImpl.java b/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointDistanceQueryImpl.java index 46dcce9553f..a360fdbaf08 100644 --- a/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointDistanceQueryImpl.java +++ b/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointDistanceQueryImpl.java @@ -16,9 +16,9 @@ */ package org.apache.lucene.spatial.geopoint.search; +import org.apache.lucene.geo.Rectangle; import org.apache.lucene.search.MultiTermQuery; import org.apache.lucene.spatial.geopoint.document.GeoPointField.TermEncoding; -import org.apache.lucene.spatial.util.GeoRect; import org.apache.lucene.util.SloppyMath; /** Package private implementation for the public facing GeoPointDistanceQuery delegate class. @@ -36,7 +36,7 @@ final class GeoPointDistanceQueryImpl extends GeoPointInBBoxQueryImpl { final double axisLat; GeoPointDistanceQueryImpl(final String field, final TermEncoding termEncoding, final GeoPointDistanceQuery q, - final double centerLonUnwrapped, final GeoRect bbox) { + final double centerLonUnwrapped, final Rectangle bbox) { super(field, termEncoding, bbox.minLat, bbox.maxLat, bbox.minLon, bbox.maxLon); distanceQuery = q; centerLon = centerLonUnwrapped; @@ -49,7 +49,7 @@ final class GeoPointDistanceQueryImpl extends GeoPointInBBoxQueryImpl { } else { maxPartialDistance = Double.POSITIVE_INFINITY; } - axisLat = GeoRect.axisLat(distanceQuery.centerLat, distanceQuery.radiusMeters); + axisLat = Rectangle.axisLat(distanceQuery.centerLat, distanceQuery.radiusMeters); } @Override @@ -75,7 +75,7 @@ final class GeoPointDistanceQueryImpl extends GeoPointInBBoxQueryImpl { minLat > GeoPointDistanceQueryImpl.this.maxLat || minLon > GeoPointDistanceQueryImpl.this.maxLon) { return false; - } else if ((centerLon < minLon || centerLon > maxLon) && (axisLat+GeoRect.AXISLAT_ERROR < minLat || axisLat-GeoRect.AXISLAT_ERROR > maxLat)) { + } else if ((centerLon < minLon || centerLon > maxLon) && (axisLat+ Rectangle.AXISLAT_ERROR < minLat || axisLat- Rectangle.AXISLAT_ERROR > maxLat)) { if (SloppyMath.haversinMeters(distanceQuery.centerLat, centerLon, minLat, minLon) > distanceQuery.radiusMeters && SloppyMath.haversinMeters(distanceQuery.centerLat, centerLon, minLat, maxLon) > distanceQuery.radiusMeters && SloppyMath.haversinMeters(distanceQuery.centerLat, centerLon, maxLat, minLon) > distanceQuery.radiusMeters && diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointInPolygonQuery.java b/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointInPolygonQuery.java index 0d29d252b5a..17ce54d437d 100644 --- a/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointInPolygonQuery.java +++ b/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointInPolygonQuery.java @@ -23,8 +23,8 @@ import org.apache.lucene.search.Query; import org.apache.lucene.spatial.geopoint.document.GeoPointField; import org.apache.lucene.spatial.geopoint.document.GeoPointField.TermEncoding; import org.apache.lucene.spatial.util.GeoEncodingUtils; -import org.apache.lucene.spatial.util.GeoRect; -import org.apache.lucene.spatial.util.Polygon; +import org.apache.lucene.geo.Rectangle; +import org.apache.lucene.geo.Polygon; /** Implements a simple point in polygon query on a GeoPoint field. This is based on * {@code GeoPointInBBoxQueryImpl} and is implemented using a @@ -82,11 +82,11 @@ public final class GeoPointInPolygonQuery extends GeoPointInBBoxQuery { * that fall within or on the boundary of the polygon defined by the input parameters. */ public GeoPointInPolygonQuery(String field, TermEncoding termEncoding, Polygon... polygons) { - this(field, termEncoding, GeoRect.fromPolygon(polygons), polygons); + this(field, termEncoding, Rectangle.fromPolygon(polygons), polygons); } // internal constructor - private GeoPointInPolygonQuery(String field, TermEncoding termEncoding, GeoRect boundingBox, Polygon... polygons) { + private GeoPointInPolygonQuery(String field, TermEncoding termEncoding, Rectangle boundingBox, Polygon... polygons) { super(field, termEncoding, boundingBox.minLat, boundingBox.maxLat, boundingBox.minLon, boundingBox.maxLon); this.polygons = polygons.clone(); } diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointInPolygonQueryImpl.java b/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointInPolygonQueryImpl.java index 20c90785b63..1bb43c70ba4 100644 --- a/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointInPolygonQueryImpl.java +++ b/lucene/spatial/src/java/org/apache/lucene/spatial/geopoint/search/GeoPointInPolygonQueryImpl.java @@ -20,7 +20,7 @@ import java.util.Objects; import org.apache.lucene.search.MultiTermQuery; import org.apache.lucene.spatial.geopoint.document.GeoPointField.TermEncoding; -import org.apache.lucene.spatial.util.Polygon; +import org.apache.lucene.geo.Polygon; /** Package private implementation for the public facing GeoPointInPolygonQuery delegate class. * diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestGeoPointQuery.java b/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestGeoPointQuery.java index 91afe3fd7e2..ff8baca95c8 100644 --- a/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestGeoPointQuery.java +++ b/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestGeoPointQuery.java @@ -19,7 +19,7 @@ package org.apache.lucene.spatial.geopoint.search; import org.apache.lucene.document.Document; import org.apache.lucene.search.Query; import org.apache.lucene.spatial.util.GeoEncodingUtils; -import org.apache.lucene.spatial.util.Polygon; +import org.apache.lucene.geo.Polygon; import org.apache.lucene.spatial.geopoint.document.GeoPointField; import org.apache.lucene.spatial.geopoint.document.GeoPointField.TermEncoding; import org.apache.lucene.spatial.util.BaseGeoPointTestCase; diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestLegacyGeoPointQuery.java b/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestLegacyGeoPointQuery.java index cd15f6691a5..4c8e3e32de3 100644 --- a/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestLegacyGeoPointQuery.java +++ b/lucene/spatial/src/test/org/apache/lucene/spatial/geopoint/search/TestLegacyGeoPointQuery.java @@ -19,7 +19,7 @@ package org.apache.lucene.spatial.geopoint.search; import org.apache.lucene.document.Document; import org.apache.lucene.search.Query; import org.apache.lucene.spatial.util.GeoEncodingUtils; -import org.apache.lucene.spatial.util.Polygon; +import org.apache.lucene.geo.Polygon; import org.apache.lucene.spatial.geopoint.document.GeoPointField; import org.apache.lucene.spatial.geopoint.document.GeoPointField.TermEncoding; import org.apache.lucene.spatial.util.BaseGeoPointTestCase; diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java b/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java index 182ec6f66d0..6ae4d20142e 100644 --- a/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java +++ b/lucene/spatial/src/test/org/apache/lucene/spatial/util/BaseGeoPointTestCase.java @@ -37,7 +37,10 @@ import org.apache.lucene.document.Field; import org.apache.lucene.document.NumericDocValuesField; import org.apache.lucene.document.StoredField; import org.apache.lucene.document.StringField; +import org.apache.lucene.geo.Rectangle; +import org.apache.lucene.geo.GeoTestUtil; import org.apache.lucene.geo.GeoUtils; +import org.apache.lucene.geo.Polygon; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; @@ -537,7 +540,7 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase { int iters = atLeast(25); for (int iter=0;iter= 0) { + hash = GeoEncodingUtils.mortonHash(nextLatitude(), nextLongitude()); + for (int i=32; i<64; ++i) { + GeoEncodingUtils.geoCodedToPrefixCoded(hash, i, brb); + decodedHash = GeoEncodingUtils.prefixCodedToGeoCoded(brb.get()); + assertEquals((hash >>> i) << i, decodedHash); + } + } + } + + public void testMortonEncoding() throws Exception { + long hash = GeoEncodingUtils.mortonHash(90, 180); + assertEquals(180.0, GeoEncodingUtils.mortonUnhashLon(hash), 0); + assertEquals(90.0, GeoEncodingUtils.mortonUnhashLat(hash), 0); + } + + public void testEncodeDecode() throws Exception { + int iters = atLeast(10000); + for(int iter=0;iter 90) { @@ -299,7 +298,7 @@ public class GeoTestUtil { return lon; } } - + private static void drawRectApproximatelyOnEarthSurface(String name, String color, double minLat, double maxLat, double minLon, double maxLon) { int steps = 20; System.out.println(" var " + name + " = WE.polygon(["); @@ -324,7 +323,7 @@ public class GeoTestUtil { System.out.println(" ], {color: \"" + color + "\", fillColor: \"" + color + "\"});"); System.out.println(" " + name + ".addTo(earth);"); } - + private static void plotLatApproximatelyOnEarthSurface(String name, String color, double lat, double minLon, double maxLon) { System.out.println(" var " + name + " = WE.polygon(["); double lon; @@ -373,7 +372,7 @@ public class GeoTestUtil { double lon = poly[1][i]; System.out.println(" [" + lat + ", " + lon + "],"); } - System.out.println(" ], {color: '#00ff00'});"); + System.out.println(" ], {color: '#00ff00'});"); System.out.println(" poly" + count + ".addTo(earth);"); } @@ -399,7 +398,7 @@ public class GeoTestUtil { double rectMinLongitude, double rectMaxLongitude, double centerLatitude, double centerLongitude, double radiusMeters) { - GeoRect box = GeoRect.fromPointDistance(centerLatitude, centerLongitude, radiusMeters); + Rectangle box = Rectangle.fromPointDistance(centerLatitude, centerLongitude, radiusMeters); System.out.println(""); System.out.println(""); System.out.println(" "); @@ -413,7 +412,7 @@ public class GeoTestUtil { StringBuilder b = new StringBuilder(); inverseHaversin(b, centerLatitude, centerLongitude, radiusMeters); System.out.println(b); - System.out.println(" ], {color: '#00ff00'});"); + System.out.println(" ], {color: '#00ff00'});"); System.out.println(" polygonB.addTo(earth);"); drawRectApproximatelyOnEarthSurface("bbox", "#00ff00", box.minLat, box.maxLat, box.minLon, box.maxLon); System.out.println(" WE.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{"); @@ -421,7 +420,7 @@ public class GeoTestUtil { System.out.println(" }).addTo(earth);"); plotLatApproximatelyOnEarthSurface("lat0", "#ffffff", 4.68, 0.0, 360.0); plotLatApproximatelyOnEarthSurface("lat1", "#ffffff", 180-93.09, 0.0, 360.0); - plotLatApproximatelyOnEarthSurface("axisLat", "#00ff00", GeoRect.axisLat(centerLatitude, radiusMeters), box.minLon, box.maxLon); + plotLatApproximatelyOnEarthSurface("axisLat", "#00ff00", Rectangle.axisLat(centerLatitude, radiusMeters), box.minLon, box.maxLon); plotLonApproximatelyOnEarthSurface("axisLon", "#00ff00", centerLongitude, box.minLat, box.maxLat); System.out.println(" }"); System.out.println(" "); diff --git a/lucene/test-framework/src/java/org/apache/lucene/geo/package-info.java b/lucene/test-framework/src/java/org/apache/lucene/geo/package-info.java new file mode 100644 index 00000000000..9f0340bd572 --- /dev/null +++ b/lucene/test-framework/src/java/org/apache/lucene/geo/package-info.java @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Reusable Geo test utilities. + */ +package org.apache.lucene.geo; \ No newline at end of file