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 1c54f4e5222..ce908e70ef1 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 @@ -82,41 +82,11 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase { private static double originLat; private static double originLon; - private static double lonRange; - private static double latRange; @BeforeClass public static void beforeClassBase() throws Exception { - // Between 1.0 and 3.0: - lonRange = 2 * (random().nextDouble() + 0.5); - latRange = 2 * (random().nextDouble() + 0.5); - - originLon = normalizeLon(GeoUtils.MIN_LON_INCL + lonRange + (GeoUtils.MAX_LON_INCL - GeoUtils.MIN_LON_INCL - 2 * lonRange) * random().nextDouble()); - originLat = normalizeLat(GeoUtils.MIN_LAT_INCL + latRange + (GeoUtils.MAX_LAT_INCL - GeoUtils.MIN_LAT_INCL - 2 * latRange) * random().nextDouble()); - } - - /** Puts longitude in range of -180 to +180. */ - public static double normalizeLon(double lon_deg) { - if (lon_deg >= -180 && lon_deg <= 180) { - return lon_deg; //common case, and avoids slight double precision shifting - } - double off = (lon_deg + 180) % 360; - if (off < 0) { - return 180 + off; - } else if (off == 0 && lon_deg > 0) { - return 180; - } else { - return -180 + off; - } - } - - /** Puts latitude in range of -90 to 90. */ - public static double normalizeLat(double lat_deg) { - if (lat_deg >= -90 && lat_deg <= 90) { - return lat_deg; //common case, and avoids slight double precision shifting - } - double off = Math.abs((lat_deg + 90) % 360); - return (off <= 180 ? off : 360-off) - 90; + originLon = GeoTestUtil.nextLongitude(); + originLat = GeoTestUtil.nextLatitude(); } /** Valid values that should not cause exception */ @@ -621,9 +591,9 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase { public double randomLat(boolean small) { double result; if (small) { - result = normalizeLat(originLat + latRange * (random().nextDouble() - 0.5)); + result = GeoTestUtil.nextLatitudeNear(originLat); } else { - result = -90 + 180.0 * random().nextDouble(); + result = GeoTestUtil.nextLatitude(); } return quantizeLat(result); } @@ -631,9 +601,9 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase { public double randomLon(boolean small) { double result; if (small) { - result = normalizeLon(originLon + lonRange * (random().nextDouble() - 0.5)); + result = GeoTestUtil.nextLongitudeNear(originLon); } else { - result = -180 + 360.0 * random().nextDouble(); + result = GeoTestUtil.nextLongitude(); } return quantizeLon(result); } @@ -1107,8 +1077,8 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase { RandomIndexWriter writer = new RandomIndexWriter(random(), dir, iwc); for (int i = 0; i < numDocs; i++) { - double latRaw = -90 + 180.0 * random().nextDouble(); - double lonRaw = -180 + 360.0 * random().nextDouble(); + double latRaw = GeoTestUtil.nextLatitude(); + double lonRaw = GeoTestUtil.nextLongitude(); // pre-normalize up front, so we can just use quantized value for testing and do simple exact comparisons double lat = quantizeLat(latRaw); double lon = quantizeLon(lonRaw); @@ -1122,8 +1092,8 @@ public abstract class BaseGeoPointTestCase extends LuceneTestCase { IndexSearcher searcher = newSearcher(reader); for (int i = 0; i < numQueries; i++) { - double lat = -90 + 180.0 * random().nextDouble(); - double lon = -180 + 360.0 * random().nextDouble(); + double lat = GeoTestUtil.nextLatitude(); + double lon = GeoTestUtil.nextLongitude(); double radius = 50000000D * random().nextDouble(); BitSet expected = new BitSet(); diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/util/GeoTestUtil.java b/lucene/spatial/src/test/org/apache/lucene/spatial/util/GeoTestUtil.java new file mode 100644 index 00000000000..f28e623f5f1 --- /dev/null +++ b/lucene/spatial/src/test/org/apache/lucene/spatial/util/GeoTestUtil.java @@ -0,0 +1,104 @@ +/* + * 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. + */ +package org.apache.lucene.spatial.util; + +import java.util.Random; + +import com.carrotsearch.randomizedtesting.RandomizedContext; + +/** static methods for testing geo */ +public class GeoTestUtil { + + /** returns next pseudorandom latitude (anywhere) */ + public static double nextLatitude() { + return -90 + 180.0 * random().nextDouble(); + } + + + /** returns next pseudorandom longitude (anywhere) */ + public static double nextLongitude() { + return -180 + 360.0 * random().nextDouble(); + } + + /** returns next pseudorandom latitude, kinda close to {@code otherLatitude} */ + public static double nextLatitudeNear(double otherLatitude) { + GeoUtils.checkLatitude(otherLatitude); + return normalizeLatitude(otherLatitude + random().nextDouble() - 0.5); + } + + /** returns next pseudorandom longitude, kinda close to {@code otherLongitude} */ + public static double nextLongitudeNear(double otherLongitude) { + GeoUtils.checkLongitude(otherLongitude); + return normalizeLongitude(otherLongitude + random().nextDouble() - 0.5); + } + + /** + * returns next pseudorandom latitude, kinda close to {@code minLatitude/maxLatitude} + * NOTE:minLatitude/maxLatitude are merely guidelines. the returned value is sometimes + * outside of that range! this is to facilitate edge testing. + */ + public static double nextLatitudeAround(double minLatitude, double maxLatitude) { + GeoUtils.checkLatitude(minLatitude); + GeoUtils.checkLatitude(maxLatitude); + return normalizeLatitude(randomRangeMaybeSlightlyOutside(minLatitude, maxLatitude)); + } + + /** + * returns next pseudorandom longitude, kinda close to {@code minLongitude/maxLongitude} + * NOTE:minLongitude/maxLongitude are merely guidelines. the returned value is sometimes + * outside of that range! this is to facilitate edge testing. + */ + public static double nextLongitudeAround(double minLongitude, double maxLongitude) { + GeoUtils.checkLongitude(minLongitude); + GeoUtils.checkLongitude(maxLongitude); + return normalizeLongitude(randomRangeMaybeSlightlyOutside(minLongitude, maxLongitude)); + } + + /** Returns random double min to max or up to 1% outside of that range */ + private static double randomRangeMaybeSlightlyOutside(double min, double max) { + return min + (random().nextDouble() + (0.5 - random().nextDouble()) * .02) * (max - min); + } + + /** Puts latitude in range of -90 to 90. */ + private static double normalizeLatitude(double latitude) { + if (latitude >= -90 && latitude <= 90) { + return latitude; //common case, and avoids slight double precision shifting + } + double off = Math.abs((latitude + 90) % 360); + return (off <= 180 ? off : 360-off) - 90; + } + + /** Puts longitude in range of -180 to +180. */ + private static double normalizeLongitude(double longitude) { + if (longitude >= -180 && longitude <= 180) { + return longitude; //common case, and avoids slight double precision shifting + } + double off = (longitude + 180) % 360; + if (off < 0) { + return 180 + off; + } else if (off == 0 && longitude > 0) { + return 180; + } else { + return -180 + off; + } + } + + /** Keep it simple, we don't need to take arbitrary Random for geo tests */ + private static Random random() { + return RandomizedContext.current().getRandom(); + } +} diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/util/TestGeoUtils.java b/lucene/spatial/src/test/org/apache/lucene/spatial/util/TestGeoUtils.java index 15fa29c0915..10baf42ed39 100644 --- a/lucene/spatial/src/test/org/apache/lucene/spatial/util/TestGeoUtils.java +++ b/lucene/spatial/src/test/org/apache/lucene/spatial/util/TestGeoUtils.java @@ -34,24 +34,11 @@ public class TestGeoUtils extends LuceneTestCase { // Global bounding box we will "cover" in the random test; we have to make this "smallish" else the queries take very long: private static double originLat; private static double originLon; - // private static double range; - private static double lonRange; - private static double latRange; @BeforeClass public static void beforeClass() throws Exception { - // Between 1.0 and 3.0: - lonRange = 2 * (random().nextDouble() + 0.5); - latRange = 2 * (random().nextDouble() + 0.5); - - originLon = GeoUtils.MIN_LON_INCL + lonRange + (GeoUtils.MAX_LON_INCL - GeoUtils.MIN_LON_INCL - 2 * lonRange) * random().nextDouble(); - originLon = BaseGeoPointTestCase.normalizeLon(originLon); - originLat = GeoUtils.MIN_LAT_INCL + latRange + (GeoUtils.MAX_LAT_INCL - GeoUtils.MIN_LAT_INCL - 2 * latRange) * random().nextDouble(); - originLat = BaseGeoPointTestCase.normalizeLat(originLat); - - if (VERBOSE) { - System.out.println("TEST: originLon=" + originLon + " lonRange= " + lonRange + " originLat=" + originLat + " latRange=" + latRange); - } + originLon = GeoTestUtil.nextLongitude(); + originLat = GeoTestUtil.nextLatitude(); } public long scaleLon(final double val) { @@ -73,9 +60,9 @@ public class TestGeoUtils extends LuceneTestCase { public double randomLat(boolean small) { double result; if (small) { - result = BaseGeoPointTestCase.normalizeLat(originLat + latRange * (random().nextDouble() - 0.5)); + result = GeoTestUtil.nextLatitudeNear(originLat); } else { - result = -90 + 180.0 * random().nextDouble(); + result = GeoTestUtil.nextLatitude(); } return result; } @@ -83,9 +70,9 @@ public class TestGeoUtils extends LuceneTestCase { public double randomLon(boolean small) { double result; if (small) { - result = BaseGeoPointTestCase.normalizeLon(originLon + lonRange * (random().nextDouble() - 0.5)); + result = GeoTestUtil.nextLongitudeNear(originLon); } else { - result = -180 + 360.0 * random().nextDouble(); + result = GeoTestUtil.nextLongitude(); } return result; } @@ -149,11 +136,6 @@ public class TestGeoUtils extends LuceneTestCase { } } - /** Returns random double min to max or up to 1% outside of that range */ - private double randomRangeMaybeSlightlyOutside(double min, double max) { - return min + (random().nextDouble() + (0.5 - random().nextDouble()) * .02) * (max - min); - } - // We rely heavily on GeoUtils.circleToBBox so we test it here: public void testRandomCircleToBBox() throws Exception { int iters = atLeast(1000); @@ -188,15 +170,15 @@ public class TestGeoUtils extends LuceneTestCase { lon = randomLon(useSmallRanges); } else { // pick a lat/lon within the bbox or "slightly" outside it to try to improve test efficiency - lat = BaseGeoPointTestCase.normalizeLat(randomRangeMaybeSlightlyOutside(bbox.minLat, bbox.maxLat)); + lat = GeoTestUtil.nextLatitudeAround(bbox.minLat, bbox.maxLat); if (bbox.crossesDateline()) { if (random().nextBoolean()) { - lon = BaseGeoPointTestCase.normalizeLon(randomRangeMaybeSlightlyOutside(bbox.maxLon, -180)); + lon = GeoTestUtil.nextLongitudeAround(bbox.maxLon, -180); } else { - lon = BaseGeoPointTestCase.normalizeLon(randomRangeMaybeSlightlyOutside(0, bbox.minLon)); + lon = GeoTestUtil.nextLongitudeAround(0, bbox.minLon); } } else { - lon = BaseGeoPointTestCase.normalizeLon(randomRangeMaybeSlightlyOutside(bbox.minLon, bbox.maxLon)); + lon = GeoTestUtil.nextLongitudeAround(bbox.minLon, bbox.maxLon); } } @@ -235,8 +217,8 @@ public class TestGeoUtils extends LuceneTestCase { // similar to testRandomCircleToBBox, but different, less evil, maybe simpler public void testBoundingBoxOpto() { for (int i = 0; i < 1000; i++) { - double lat = -90 + 180.0 * random().nextDouble(); - double lon = -180 + 360.0 * random().nextDouble(); + double lat = GeoTestUtil.nextLatitude(); + double lon = GeoTestUtil.nextLongitude(); double radius = 50000000 * random().nextDouble(); GeoRect box = GeoUtils.circleToBBox(lat, lon, radius); final GeoRect box1; @@ -250,8 +232,8 @@ public class TestGeoUtils extends LuceneTestCase { } for (int j = 0; j < 10000; j++) { - double lat2 = -90 + 180.0 * random().nextDouble(); - double lon2 = -180 + 360.0 * random().nextDouble(); + double lat2 = GeoTestUtil.nextLatitude(); + double lon2 = GeoTestUtil.nextLongitude(); // if the point is within radius, then it should be in our bounding box if (SloppyMath.haversinMeters(lat, lon, lat2, lon2) <= radius) { assertTrue(lat >= box.minLat && lat <= box.maxLat); @@ -264,8 +246,8 @@ public class TestGeoUtils extends LuceneTestCase { // test we can use haversinSortKey() for distance queries. public void testHaversinOpto() { for (int i = 0; i < 1000; i++) { - double lat = -90 + 180.0 * random().nextDouble(); - double lon = -180 + 360.0 * random().nextDouble(); + double lat = GeoTestUtil.nextLatitude(); + double lon = GeoTestUtil.nextLongitude(); double radius = 50000000 * random().nextDouble(); GeoRect box = GeoUtils.circleToBBox(lat, lon, radius); @@ -274,8 +256,8 @@ public class TestGeoUtils extends LuceneTestCase { SloppyMath.haversinSortKey(lat, lon, box.maxLat, lon)); for (int j = 0; j < 10000; j++) { - double lat2 = -90 + 180.0 * random().nextDouble(); - double lon2 = -180 + 360.0 * random().nextDouble(); + double lat2 = GeoTestUtil.nextLatitude(); + double lon2 = GeoTestUtil.nextLongitude(); // if the point is within radius, then it should be <= our sort key if (SloppyMath.haversinMeters(lat, lon, lat2, lon2) <= radius) { assertTrue(SloppyMath.haversinSortKey(lat, lon, lat2, lon2) <= minPartialDistance); @@ -288,8 +270,8 @@ public class TestGeoUtils extends LuceneTestCase { /** Test infinite radius covers whole earth */ public void testInfiniteRect() { for (int i = 0; i < 1000; i++) { - double centerLat = -90 + 180.0 * random().nextDouble(); - double centerLon = -180 + 360.0 * random().nextDouble(); + double centerLat = GeoTestUtil.nextLatitude(); + double centerLon = GeoTestUtil.nextLongitude(); GeoRect rect = GeoUtils.circleToBBox(centerLat, centerLon, Double.POSITIVE_INFINITY); assertEquals(-180.0, rect.minLon, 0.0D); assertEquals(180.0, rect.maxLon, 0.0D);