|
|
@@ -7,6 +7,7 @@
|
|
|
|
|
|
package org.elasticsearch.xpack.spatial.search.aggregations.bucket.geogrid;
|
|
|
|
|
|
+import org.apache.lucene.geo.GeoTestUtil;
|
|
|
import org.elasticsearch.common.breaker.CircuitBreaker;
|
|
|
import org.elasticsearch.common.breaker.CircuitBreakingException;
|
|
|
import org.elasticsearch.common.geo.GeoBoundingBox;
|
|
|
@@ -225,6 +226,58 @@ public class GeoGridTilerTests extends ESTestCase {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public void testGeoHashBoundsExcludeTouchingTiles() throws Exception {
|
|
|
+ final int precision = randomIntBetween(1, 5);
|
|
|
+ final String hash =
|
|
|
+ Geohash.stringEncode(GeoTestUtil.nextLongitude(), GeoTestUtil.nextLatitude(), precision);
|
|
|
+
|
|
|
+ final Rectangle rectangle = Geohash.toBoundingBox(hash);
|
|
|
+ final GeoBoundingBox box = new GeoBoundingBox(
|
|
|
+ new GeoPoint(rectangle.getMaxLat(), rectangle.getMinLon()),
|
|
|
+ new GeoPoint(rectangle.getMinLat(), rectangle.getMaxLon())
|
|
|
+ );
|
|
|
+ final Rectangle other = new Rectangle(
|
|
|
+ Math.max(-180, rectangle.getMinX() - 1),
|
|
|
+ Math.min(180, rectangle.getMaxX() + 1),
|
|
|
+ Math.min(90, rectangle.getMaxY() + 1),
|
|
|
+ Math.max(-90, rectangle.getMinY() - 1));
|
|
|
+ final GeoShapeValues.GeoShapeValue value = geoShapeValue(other);
|
|
|
+ for (int i = 0; i < 4; i++) {
|
|
|
+ final BoundedGeoHashGridTiler bounded = new BoundedGeoHashGridTiler(precision + i, box);
|
|
|
+ final GeoShapeCellValues values = new GeoShapeCellValues(makeGeoShapeValues(value), bounded, NOOP_BREAKER);
|
|
|
+ assertTrue(values.advanceExact(0));
|
|
|
+ final int numTiles = values.docValueCount();
|
|
|
+ final int expected = (int) Math.pow(32, i);
|
|
|
+ assertThat(numTiles, equalTo(expected));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testGeoTileBoundsExcludeTouchingTiles() throws Exception {
|
|
|
+ final int z = randomIntBetween(1, GeoTileUtils.MAX_ZOOM - 10);
|
|
|
+ final int x = randomIntBetween(0, (1 << z) - 1);
|
|
|
+ final int y = randomIntBetween(0, (1 << z) - 1);
|
|
|
+ final Rectangle rectangle = GeoTileUtils.toBoundingBox(x, y, z);
|
|
|
+ final GeoBoundingBox box = new GeoBoundingBox(
|
|
|
+ new GeoPoint(rectangle.getMaxLat(), rectangle.getMinLon()),
|
|
|
+ new GeoPoint(rectangle.getMinLat(), rectangle.getMaxLon())
|
|
|
+ );
|
|
|
+ final Rectangle other = new Rectangle(
|
|
|
+ Math.max(-180, rectangle.getMinX() - 1),
|
|
|
+ Math.min(180, rectangle.getMaxX() + 1),
|
|
|
+ Math.min(90, rectangle.getMaxY() + 1),
|
|
|
+ Math.max(-90, rectangle.getMinY() - 1));
|
|
|
+ final GeoShapeValues.GeoShapeValue value = geoShapeValue(other);
|
|
|
+ for (int i = 0; i < 10; i++) {
|
|
|
+ final BoundedGeoTileGridTiler bounded = new BoundedGeoTileGridTiler(z + i, box);
|
|
|
+ final GeoShapeCellValues values = new GeoShapeCellValues(makeGeoShapeValues(value), bounded, NOOP_BREAKER);
|
|
|
+ assertTrue(values.advanceExact(0));
|
|
|
+ final int numTiles = values.docValueCount();
|
|
|
+ final int expected = 1 << (2 * i);
|
|
|
+ assertThat(numTiles, equalTo(expected));
|
|
|
+ assertThat((int) bounded.getMaxTiles(), equalTo(expected));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public void testGeoTileShapeContainsBound() throws Exception {
|
|
|
Rectangle tile = GeoTileUtils.toBoundingBox(44140, 44140, 16);
|
|
|
Rectangle shapeRectangle = new Rectangle(tile.getMinX() - 15, tile.getMaxX() + 15,
|
|
|
@@ -235,12 +288,32 @@ public class GeoGridTilerTests extends ESTestCase {
|
|
|
new GeoPoint(tile.getMaxLat(), tile.getMinLon()),
|
|
|
new GeoPoint(tile.getMinLat(), tile.getMaxLon())
|
|
|
);
|
|
|
+ BoundedGeoTileGridTiler tiler = new BoundedGeoTileGridTiler(24, boundingBox);
|
|
|
+ GeoShapeCellValues values =
|
|
|
+ new GeoShapeCellValues(makeGeoShapeValues(value), tiler, NOOP_BREAKER);
|
|
|
+ assertTrue(values.advanceExact(0));
|
|
|
+ int numTiles = values.docValueCount();
|
|
|
+ int expectedTiles = Math.toIntExact(tiler.getMaxTiles());
|
|
|
+ assertThat(numTiles, equalTo(expectedTiles));
|
|
|
+ assertThat(numTiles, equalTo(256 * 256));
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testGeoTileShapeContainsBound3() throws Exception {
|
|
|
+ Rectangle tile = GeoTileUtils.toBoundingBox(2, 2, 3);
|
|
|
+ Rectangle shapeRectangle = new Rectangle(tile.getMinX() - 1, tile.getMaxX() + 1,
|
|
|
+ tile.getMaxY() + 1, tile.getMinY() - 1);
|
|
|
+ GeoShapeValues.GeoShapeValue value = geoShapeValue(shapeRectangle);
|
|
|
+
|
|
|
+ GeoBoundingBox boundingBox = new GeoBoundingBox(
|
|
|
+ new GeoPoint(tile.getMaxLat(), tile.getMinLon()),
|
|
|
+ new GeoPoint(tile.getMinLat(), tile.getMaxLon())
|
|
|
+ );
|
|
|
+ BoundedGeoTileGridTiler tiler = new BoundedGeoTileGridTiler(4, boundingBox);
|
|
|
GeoShapeCellValues values =
|
|
|
- new GeoShapeCellValues(makeGeoShapeValues(value), new BoundedGeoTileGridTiler(24, boundingBox), NOOP_BREAKER);
|
|
|
+ new GeoShapeCellValues(makeGeoShapeValues(value), tiler, NOOP_BREAKER);
|
|
|
assertTrue(values.advanceExact(0));
|
|
|
int numTiles = values.docValueCount();
|
|
|
- int expectedTiles =
|
|
|
- (int) AbstractGeoTileGridTiler.numTilesFromPrecision(24, tile.getMinX(), tile.getMaxX(), tile.getMinY(), tile.getMaxY());
|
|
|
+ int expectedTiles = Math.toIntExact(tiler.getMaxTiles());
|
|
|
assertThat(expectedTiles, equalTo(numTiles));
|
|
|
}
|
|
|
|
|
|
@@ -253,43 +326,47 @@ public class GeoGridTilerTests extends ESTestCase {
|
|
|
new GeoPoint(tile.getMaxLat(), tile.getMinLon()),
|
|
|
new GeoPoint(tile.getMinLat(), tile.getMaxLon())
|
|
|
);
|
|
|
+ BoundedGeoTileGridTiler tiler = new BoundedGeoTileGridTiler(13, boundingBox);
|
|
|
GeoShapeCellValues values =
|
|
|
new GeoShapeCellValues(makeGeoShapeValues(value), new BoundedGeoTileGridTiler(13, boundingBox), NOOP_BREAKER);
|
|
|
assertTrue(values.advanceExact(0));
|
|
|
int numTiles = values.docValueCount();
|
|
|
- int expectedTiles = (int) (AbstractGeoTileGridTiler.numTilesFromPrecision(13, 178, 180, -2, 2)
|
|
|
- + AbstractGeoTileGridTiler.numTilesFromPrecision(13, -180, -178, -2, 2));
|
|
|
+ int expectedTiles = Math.toIntExact(tiler.getMaxTiles());
|
|
|
assertThat(expectedTiles, equalTo(numTiles));
|
|
|
}
|
|
|
|
|
|
- private boolean tileIntersectsBounds(int x, int y, int precision, GeoBoundingBox bounds) {
|
|
|
- if (bounds == null) {
|
|
|
+ private boolean tileIntersectsBounds(int x, int y, int precision, GeoBoundingBox bbox) {
|
|
|
+ if (bbox == null) {
|
|
|
return true;
|
|
|
}
|
|
|
- final double boundsWestLeft;
|
|
|
- final double boundsWestRight;
|
|
|
- final double boundsEastLeft;
|
|
|
- final double boundsEastRight;
|
|
|
- final boolean crossesDateline;
|
|
|
- if (bounds.right() < bounds.left()) {
|
|
|
- boundsWestLeft = -180;
|
|
|
- boundsWestRight = bounds.right();
|
|
|
- boundsEastLeft = bounds.left();
|
|
|
- boundsEastRight = 180;
|
|
|
- crossesDateline = true;
|
|
|
- } else {
|
|
|
- boundsEastLeft = bounds.left();
|
|
|
- boundsEastRight = bounds.right();
|
|
|
- boundsWestLeft = 0;
|
|
|
- boundsWestRight = 0;
|
|
|
- crossesDateline = false;
|
|
|
+ final int tiles = 1 << precision;
|
|
|
+ int minX = GeoTileUtils.getXTile(bbox.left(), tiles);
|
|
|
+ int minY = GeoTileUtils.getYTile(bbox.top(), tiles);
|
|
|
+ final Rectangle minTile = GeoTileUtils.toBoundingBox(minX, minY, precision);
|
|
|
+ if (minTile.getMaxX() == bbox.left()) {
|
|
|
+ minX++;
|
|
|
}
|
|
|
-
|
|
|
- Rectangle tile = GeoTileUtils.toBoundingBox(x, y, precision);
|
|
|
-
|
|
|
- return (bounds.top() >= tile.getMinY() && bounds.bottom() <= tile.getMaxY()
|
|
|
- && (boundsEastLeft <= tile.getMaxX() && boundsEastRight >= tile.getMinX()
|
|
|
- || (crossesDateline && boundsWestLeft <= tile.getMaxX() && boundsWestRight >= tile.getMinX())));
|
|
|
+ if (minTile.getMinY() == bbox.top()) {
|
|
|
+ minY++;
|
|
|
+ }
|
|
|
+ // compute maxX, maxY
|
|
|
+ int maxX = GeoTileUtils.getXTile(bbox.right(), tiles);
|
|
|
+ int maxY = GeoTileUtils.getYTile(bbox.bottom(), tiles);
|
|
|
+ final Rectangle maxTile = GeoTileUtils.toBoundingBox(maxX, maxY, precision);
|
|
|
+ if (maxTile.getMinX() == bbox.right()) {
|
|
|
+ maxX--;
|
|
|
+ }
|
|
|
+ if (maxTile.getMaxY() == bbox.bottom()) {
|
|
|
+ maxY--;
|
|
|
+ }
|
|
|
+ if (maxY >= y && minY <= y) {
|
|
|
+ if (bbox.left() > bbox.right()) {
|
|
|
+ return maxX >= x || minX <= x;
|
|
|
+ } else {
|
|
|
+ return maxX >= x && minX <= x;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
private int numTiles(GeoShapeValues.GeoShapeValue geoValue, int precision, GeoBoundingBox geoBox) {
|